123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854 |
- /*
- * Neighbor Awareness Networking
- *
- * Portions of this code are copyright (c) 2020 Cypress Semiconductor Corporation
- *
- * Copyright (C) 1999-2020, Broadcom Corporation
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- *
- * As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module. An independent module is a module which is not
- * derived from this software. The special exception does not apply to any
- * modifications of the software.
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- *
- * <<Broadcom-WL-IPTag/Open:>>
- *
- * $Id: wl_cfgnan.c 815812 2019-04-20 14:30:23Z $
- */
- #ifdef WL_NAN
- #include <bcmutils.h>
- #include <bcmendian.h>
- #include <bcmwifi_channels.h>
- #include <nan.h>
- #include <bcmiov.h>
- #include <wl_cfg80211.h>
- #include <wl_cfgscan.h>
- #include <wl_android.h>
- #include <wl_cfgnan.h>
- #include <dngl_stats.h>
- #include <dhd.h>
- #ifdef RTT_SUPPORT
- #include <dhd_rtt.h>
- #endif /* RTT_SUPPORT */
- #include <wl_cfgvendor.h>
- #include <bcmbloom.h>
- #include <wl_cfgp2p.h>
- #ifdef RTT_SUPPORT
- #include <dhd_rtt.h>
- #endif /* RTT_SUPPORT */
- #include <bcmstdlib_s.h>
- #define NAN_RANGE_REQ_EVNT 1
- #define NAN_RAND_MAC_RETRIES 10
- #define NAN_SCAN_DWELL_TIME_DELTA_MS 10
- #define NAN_RNG_TERM_FLAG_NONE 0
- #ifdef WL_NAN_DISC_CACHE
- /* Disc Cache Parameters update Flags */
- #define NAN_DISC_CACHE_PARAM_SDE_CONTROL 0x0001
- static int wl_cfgnan_cache_disc_result(struct bcm_cfg80211 *cfg, void * data,
- u16 *disc_cache_update_flags);
- static int wl_cfgnan_remove_disc_result(struct bcm_cfg80211 * cfg, uint8 local_subid);
- static nan_disc_result_cache * wl_cfgnan_get_disc_result(struct bcm_cfg80211 *cfg,
- uint8 remote_pubid, struct ether_addr *peer);
- #endif /* WL_NAN_DISC_CACHE */
- static int wl_cfgnan_clear_disc_cache(struct bcm_cfg80211 *cfg, wl_nan_instance_id_t sub_id);
- static void wl_cfgnan_update_dp_mask(struct bcm_cfg80211 *cfg, bool enable, u8 nan_dp_id);
- static int wl_cfgnan_set_if_addr(struct bcm_cfg80211 *cfg);
- static int wl_cfgnan_get_capability(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_hal_capabilities_t *capabilities);
- static int32 wl_cfgnan_notify_disc_with_ranging(struct bcm_cfg80211 *cfg,
- nan_ranging_inst_t *rng_inst, nan_event_data_t *nan_event_data, uint32 distance);
- static void wl_cfgnan_disc_result_on_geofence_cancel(struct bcm_cfg80211 *cfg,
- nan_ranging_inst_t *rng_inst);
- static void wl_cfgnan_clear_nan_event_data(struct bcm_cfg80211 *cfg,
- nan_event_data_t *nan_event_data);
- void wl_cfgnan_data_remove_peer(struct bcm_cfg80211 *cfg,
- struct ether_addr *peer_addr);
- static void wl_cfgnan_send_stop_event(struct bcm_cfg80211 *cfg);
- #ifdef RTT_SUPPORT
- static s32 wl_cfgnan_clear_peer_ranging(struct bcm_cfg80211 * cfg,
- struct ether_addr * peer, int reason);
- #endif /* RTT_SUPPORT */
- static const char *nan_role_to_str(u8 role)
- {
- switch (role) {
- C2S(WL_NAN_ROLE_AUTO)
- C2S(WL_NAN_ROLE_NON_MASTER_NON_SYNC)
- C2S(WL_NAN_ROLE_NON_MASTER_SYNC)
- C2S(WL_NAN_ROLE_MASTER)
- C2S(WL_NAN_ROLE_ANCHOR_MASTER)
- default:
- return "WL_NAN_ROLE_UNKNOWN";
- }
- }
- static const char *nan_event_to_str(u16 cmd)
- {
- switch (cmd) {
- C2S(WL_NAN_EVENT_START)
- C2S(WL_NAN_EVENT_DISCOVERY_RESULT)
- C2S(WL_NAN_EVENT_TERMINATED)
- C2S(WL_NAN_EVENT_RECEIVE)
- C2S(WL_NAN_EVENT_MERGE)
- C2S(WL_NAN_EVENT_STOP)
- C2S(WL_NAN_EVENT_PEER_DATAPATH_IND)
- C2S(WL_NAN_EVENT_DATAPATH_ESTB)
- C2S(WL_NAN_EVENT_SDF_RX)
- C2S(WL_NAN_EVENT_DATAPATH_END)
- C2S(WL_NAN_EVENT_RNG_REQ_IND)
- C2S(WL_NAN_EVENT_RNG_RPT_IND)
- C2S(WL_NAN_EVENT_RNG_TERM_IND)
- C2S(WL_NAN_EVENT_TXS)
- C2S(WL_NAN_EVENT_INVALID)
- default:
- return "WL_NAN_EVENT_UNKNOWN";
- }
- }
- static int wl_cfgnan_execute_ioctl(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, bcm_iov_batch_buf_t *nan_buf,
- uint16 nan_buf_size, uint32 *status, uint8 *resp_buf,
- uint16 resp_buf_len);
- int
- wl_cfgnan_generate_inst_id(struct bcm_cfg80211 *cfg, uint8 *p_inst_id)
- {
- s32 ret = BCME_OK;
- uint8 i = 0;
- if (p_inst_id == NULL) {
- WL_ERR(("Invalid arguments\n"));
- ret = -EINVAL;
- goto exit;
- }
- if (cfg->nancfg.inst_id_start == NAN_ID_MAX) {
- WL_ERR(("Consumed all IDs, resetting the counter\n"));
- cfg->nancfg.inst_id_start = 0;
- }
- for (i = cfg->nancfg.inst_id_start; i < NAN_ID_MAX; i++) {
- if (isclr(cfg->nancfg.svc_inst_id_mask, i)) {
- setbit(cfg->nancfg.svc_inst_id_mask, i);
- *p_inst_id = i + 1;
- cfg->nancfg.inst_id_start = *p_inst_id;
- WL_DBG(("Instance ID=%d\n", *p_inst_id));
- goto exit;
- }
- }
- WL_ERR(("Allocated maximum IDs\n"));
- ret = BCME_NORESOURCE;
- exit:
- return ret;
- }
- int
- wl_cfgnan_remove_inst_id(struct bcm_cfg80211 *cfg, uint8 inst_id)
- {
- s32 ret = BCME_OK;
- WL_DBG(("%s: Removing svc instance id %d\n", __FUNCTION__, inst_id));
- clrbit(cfg->nancfg.svc_inst_id_mask, inst_id-1);
- return ret;
- }
- s32 wl_cfgnan_parse_sdea_data(osl_t *osh, const uint8 *p_attr,
- uint16 len, nan_event_data_t *tlv_data)
- {
- const wifi_nan_svc_desc_ext_attr_t *nan_svc_desc_ext_attr = NULL;
- uint8 offset;
- s32 ret = BCME_OK;
- /* service descriptor ext attributes */
- nan_svc_desc_ext_attr = (const wifi_nan_svc_desc_ext_attr_t *)p_attr;
- /* attribute ID */
- WL_TRACE(("> attr id: 0x%02x\n", nan_svc_desc_ext_attr->id));
- /* attribute length */
- WL_TRACE(("> attr len: 0x%x\n", nan_svc_desc_ext_attr->len));
- if (nan_svc_desc_ext_attr->instance_id == tlv_data->pub_id) {
- tlv_data->sde_control_flag = nan_svc_desc_ext_attr->control;
- }
- offset = sizeof(*nan_svc_desc_ext_attr);
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- if (tlv_data->sde_control_flag & NAN_SC_RANGE_LIMITED) {
- WL_TRACE(("> svc_control: range limited present\n"));
- }
- if (tlv_data->sde_control_flag & NAN_SDE_CF_SVC_UPD_IND_PRESENT) {
- WL_TRACE(("> svc_control: sdea svc specific info present\n"));
- tlv_data->sde_svc_info.dlen = (p_attr[1] | (p_attr[2] << 8));
- WL_TRACE(("> sdea svc info len: 0x%02x\n", tlv_data->sde_svc_info.dlen));
- if (!tlv_data->sde_svc_info.dlen ||
- tlv_data->sde_svc_info.dlen > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
- /* must be able to handle null msg which is not error */
- tlv_data->sde_svc_info.dlen = 0;
- WL_ERR(("sde data length is invalid\n"));
- ret = BCME_BADLEN;
- goto fail;
- }
- if (tlv_data->sde_svc_info.dlen > 0) {
- tlv_data->sde_svc_info.data = MALLOCZ(osh, tlv_data->sde_svc_info.dlen);
- if (!tlv_data->sde_svc_info.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- tlv_data->sde_svc_info.dlen = 0;
- ret = BCME_NOMEM;
- goto fail;
- }
- /* advance read pointer, consider sizeof of Service Update Indicator */
- offset = sizeof(tlv_data->sde_svc_info.dlen) - 1;
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- ret = memcpy_s(tlv_data->sde_svc_info.data, tlv_data->sde_svc_info.dlen,
- p_attr, tlv_data->sde_svc_info.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy sde_svc_info\n"));
- goto fail;
- }
- } else {
- /* must be able to handle null msg which is not error */
- tlv_data->sde_svc_info.dlen = 0;
- WL_DBG(("%s: sdea svc info length is zero, null info data\n",
- __FUNCTION__));
- }
- }
- return ret;
- fail:
- if (tlv_data->sde_svc_info.data) {
- MFREE(osh, tlv_data->sde_svc_info.data,
- tlv_data->sde_svc_info.dlen);
- tlv_data->sde_svc_info.data = NULL;
- }
- WL_DBG(("Parse SDEA event data, status = %d\n", ret));
- return ret;
- }
- /*
- * This attribute contains some mandatory fields and some optional fields
- * depending on the content of the service discovery request.
- */
- s32
- wl_cfgnan_parse_sda_data(osl_t *osh, const uint8 *p_attr,
- uint16 len, nan_event_data_t *tlv_data)
- {
- uint8 svc_control = 0, offset = 0;
- s32 ret = BCME_OK;
- const wifi_nan_svc_descriptor_attr_t *nan_svc_desc_attr = NULL;
- /* service descriptor attributes */
- nan_svc_desc_attr = (const wifi_nan_svc_descriptor_attr_t *)p_attr;
- /* attribute ID */
- WL_TRACE(("> attr id: 0x%02x\n", nan_svc_desc_attr->id));
- /* attribute length */
- WL_TRACE(("> attr len: 0x%x\n", nan_svc_desc_attr->len));
- /* service ID */
- ret = memcpy_s(tlv_data->svc_name, sizeof(tlv_data->svc_name),
- nan_svc_desc_attr->svc_hash, NAN_SVC_HASH_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy svc_hash_name:\n"));
- return ret;
- }
- WL_TRACE(("> svc_hash_name: " MACDBG "\n", MAC2STRDBG(tlv_data->svc_name)));
- /* local instance ID */
- tlv_data->local_inst_id = nan_svc_desc_attr->instance_id;
- WL_TRACE(("> local instance id: 0x%02x\n", tlv_data->local_inst_id));
- /* requestor instance ID */
- tlv_data->requestor_id = nan_svc_desc_attr->requestor_id;
- WL_TRACE(("> requestor id: 0x%02x\n", tlv_data->requestor_id));
- /* service control */
- svc_control = nan_svc_desc_attr->svc_control;
- if ((svc_control & NAN_SVC_CONTROL_TYPE_MASK) == NAN_SC_PUBLISH) {
- WL_TRACE(("> Service control type: NAN_SC_PUBLISH\n"));
- } else if ((svc_control & NAN_SVC_CONTROL_TYPE_MASK) == NAN_SC_SUBSCRIBE) {
- WL_TRACE(("> Service control type: NAN_SC_SUBSCRIBE\n"));
- } else if ((svc_control & NAN_SVC_CONTROL_TYPE_MASK) == NAN_SC_FOLLOWUP) {
- WL_TRACE(("> Service control type: NAN_SC_FOLLOWUP\n"));
- }
- offset = sizeof(*nan_svc_desc_attr);
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- /*
- * optional fields:
- * must be in order following by service descriptor attribute format
- */
- /* binding bitmap */
- if (svc_control & NAN_SC_BINDING_BITMAP_PRESENT) {
- uint16 bitmap = 0;
- WL_TRACE(("> svc_control: binding bitmap present\n"));
- /* Copy binding bitmap */
- ret = memcpy_s(&bitmap, sizeof(bitmap),
- p_attr, NAN_BINDING_BITMAP_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy bit map\n"));
- return ret;
- }
- WL_TRACE(("> sc binding bitmap: 0x%04x\n", bitmap));
- if (NAN_BINDING_BITMAP_LEN > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += NAN_BINDING_BITMAP_LEN;
- len -= NAN_BINDING_BITMAP_LEN;
- }
- /* matching filter */
- if (svc_control & NAN_SC_MATCHING_FILTER_PRESENT) {
- WL_TRACE(("> svc_control: matching filter present\n"));
- tlv_data->tx_match_filter.dlen = *p_attr++;
- WL_TRACE(("> matching filter len: 0x%02x\n",
- tlv_data->tx_match_filter.dlen));
- if (!tlv_data->tx_match_filter.dlen ||
- tlv_data->tx_match_filter.dlen > MAX_MATCH_FILTER_LEN) {
- tlv_data->tx_match_filter.dlen = 0;
- WL_ERR(("tx match filter length is invalid\n"));
- ret = -EINVAL;
- goto fail;
- }
- tlv_data->tx_match_filter.data =
- MALLOCZ(osh, tlv_data->tx_match_filter.dlen);
- if (!tlv_data->tx_match_filter.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- tlv_data->tx_match_filter.dlen = 0;
- ret = -ENOMEM;
- goto fail;
- }
- ret = memcpy_s(tlv_data->tx_match_filter.data, tlv_data->tx_match_filter.dlen,
- p_attr, tlv_data->tx_match_filter.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy tx match filter data\n"));
- goto fail;
- }
- /* advance read pointer */
- offset = tlv_data->tx_match_filter.dlen;
- if (offset > len) {
- WL_ERR(("Invalid event buffer\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- }
- /* service response filter */
- if (svc_control & NAN_SC_SR_FILTER_PRESENT) {
- WL_TRACE(("> svc_control: service response filter present\n"));
- tlv_data->rx_match_filter.dlen = *p_attr++;
- WL_TRACE(("> sr match filter len: 0x%02x\n",
- tlv_data->rx_match_filter.dlen));
- if (!tlv_data->rx_match_filter.dlen ||
- tlv_data->rx_match_filter.dlen > MAX_MATCH_FILTER_LEN) {
- tlv_data->rx_match_filter.dlen = 0;
- WL_ERR(("%s: sr matching filter length is invalid\n",
- __FUNCTION__));
- ret = BCME_BADLEN;
- goto fail;
- }
- tlv_data->rx_match_filter.data =
- MALLOCZ(osh, tlv_data->rx_match_filter.dlen);
- if (!tlv_data->rx_match_filter.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- tlv_data->rx_match_filter.dlen = 0;
- ret = BCME_NOMEM;
- goto fail;
- }
- ret = memcpy_s(tlv_data->rx_match_filter.data, tlv_data->rx_match_filter.dlen,
- p_attr, tlv_data->rx_match_filter.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy rx match filter data\n"));
- goto fail;
- }
- /* advance read pointer */
- offset = tlv_data->rx_match_filter.dlen;
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- }
- /* service specific info */
- if (svc_control & NAN_SC_SVC_INFO_PRESENT) {
- WL_TRACE(("> svc_control: svc specific info present\n"));
- tlv_data->svc_info.dlen = *p_attr++;
- WL_TRACE(("> svc info len: 0x%02x\n", tlv_data->svc_info.dlen));
- if (!tlv_data->svc_info.dlen ||
- tlv_data->svc_info.dlen > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
- /* must be able to handle null msg which is not error */
- tlv_data->svc_info.dlen = 0;
- WL_ERR(("sde data length is invalid\n"));
- ret = BCME_BADLEN;
- goto fail;
- }
- if (tlv_data->svc_info.dlen > 0) {
- tlv_data->svc_info.data =
- MALLOCZ(osh, tlv_data->svc_info.dlen);
- if (!tlv_data->svc_info.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- tlv_data->svc_info.dlen = 0;
- ret = BCME_NOMEM;
- goto fail;
- }
- ret = memcpy_s(tlv_data->svc_info.data, tlv_data->svc_info.dlen,
- p_attr, tlv_data->svc_info.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy svc info\n"));
- goto fail;
- }
- /* advance read pointer */
- offset = tlv_data->svc_info.dlen;
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- } else {
- /* must be able to handle null msg which is not error */
- tlv_data->svc_info.dlen = 0;
- WL_TRACE(("%s: svc info length is zero, null info data\n",
- __FUNCTION__));
- }
- }
- /*
- * discovery range limited:
- * If set to 1, the pub/sub msg is limited in range to close proximity.
- * If set to 0, the pub/sub msg is not limited in range.
- * Valid only when the message is either of a publish or a sub.
- */
- if (svc_control & NAN_SC_RANGE_LIMITED) {
- if (((svc_control & NAN_SVC_CONTROL_TYPE_MASK) == NAN_SC_PUBLISH) ||
- ((svc_control & NAN_SVC_CONTROL_TYPE_MASK) == NAN_SC_SUBSCRIBE)) {
- WL_TRACE(("> svc_control: range limited present\n"));
- } else {
- WL_TRACE(("range limited is only valid on pub or sub\n"));
- }
- /* TODO: send up */
- /* advance read pointer */
- p_attr++;
- }
- return ret;
- fail:
- if (tlv_data->tx_match_filter.data) {
- MFREE(osh, tlv_data->tx_match_filter.data,
- tlv_data->tx_match_filter.dlen);
- tlv_data->tx_match_filter.data = NULL;
- }
- if (tlv_data->rx_match_filter.data) {
- MFREE(osh, tlv_data->rx_match_filter.data,
- tlv_data->rx_match_filter.dlen);
- tlv_data->rx_match_filter.data = NULL;
- }
- if (tlv_data->svc_info.data) {
- MFREE(osh, tlv_data->svc_info.data,
- tlv_data->svc_info.dlen);
- tlv_data->svc_info.data = NULL;
- }
- WL_DBG(("Parse SDA event data, status = %d\n", ret));
- return ret;
- }
- static s32
- wl_cfgnan_parse_sd_attr_data(osl_t *osh, uint16 len, const uint8 *data,
- nan_event_data_t *tlv_data, uint16 type) {
- const uint8 *p_attr = data;
- uint16 offset = 0;
- s32 ret = BCME_OK;
- const wl_nan_event_disc_result_t *ev_disc = NULL;
- const wl_nan_event_replied_t *ev_replied = NULL;
- const wl_nan_ev_receive_t *ev_fup = NULL;
- /*
- * Mapping wifi_nan_svc_descriptor_attr_t, and svc controls are optional.
- */
- if (type == WL_NAN_XTLV_SD_DISC_RESULTS) {
- u8 iter;
- ev_disc = (const wl_nan_event_disc_result_t *)p_attr;
- WL_DBG((">> WL_NAN_XTLV_RESULTS: Discovery result\n"));
- tlv_data->pub_id = (wl_nan_instance_id_t)ev_disc->pub_id;
- tlv_data->sub_id = (wl_nan_instance_id_t)ev_disc->sub_id;
- tlv_data->publish_rssi = ev_disc->publish_rssi;
- ret = memcpy_s(&tlv_data->remote_nmi, ETHER_ADDR_LEN,
- &ev_disc->pub_mac, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy remote nmi\n"));
- goto fail;
- }
- WL_TRACE(("publish id: %d\n", ev_disc->pub_id));
- WL_TRACE(("subscribe d: %d\n", ev_disc->sub_id));
- WL_TRACE(("publish mac addr: " MACDBG "\n",
- MAC2STRDBG(ev_disc->pub_mac.octet)));
- WL_TRACE(("publish rssi: %d\n", (int8)ev_disc->publish_rssi));
- WL_TRACE(("attribute no: %d\n", ev_disc->attr_num));
- WL_TRACE(("attribute len: %d\n", (uint16)ev_disc->attr_list_len));
- /* advance to the service descricptor */
- offset = OFFSETOF(wl_nan_event_disc_result_t, attr_list[0]);
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- iter = ev_disc->attr_num;
- while (iter) {
- if ((uint8)*p_attr == NAN_ATTR_SVC_DESCRIPTOR) {
- WL_TRACE(("> attr id: 0x%02x\n", (uint8)*p_attr));
- ret = wl_cfgnan_parse_sda_data(osh, p_attr, len, tlv_data);
- if (unlikely(ret)) {
- WL_ERR(("wl_cfgnan_parse_sda_data failed,"
- "error = %d \n", ret));
- goto fail;
- }
- }
- if ((uint8)*p_attr == NAN_ATTR_SVC_DESC_EXTENSION) {
- WL_TRACE(("> attr id: 0x%02x\n", (uint8)*p_attr));
- ret = wl_cfgnan_parse_sdea_data(osh, p_attr, len, tlv_data);
- if (unlikely(ret)) {
- WL_ERR(("wl_cfgnan_parse_sdea_data failed,"
- "error = %d \n", ret));
- goto fail;
- }
- }
- offset = (sizeof(*p_attr) +
- sizeof(ev_disc->attr_list_len) +
- (p_attr[1] | (p_attr[2] << 8)));
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- iter--;
- }
- } else if (type == WL_NAN_XTLV_SD_FUP_RECEIVED) {
- uint8 iter;
- ev_fup = (const wl_nan_ev_receive_t *)p_attr;
- WL_TRACE((">> WL_NAN_XTLV_SD_FUP_RECEIVED: Transmit follow-up\n"));
- tlv_data->local_inst_id = (wl_nan_instance_id_t)ev_fup->local_id;
- tlv_data->requestor_id = (wl_nan_instance_id_t)ev_fup->remote_id;
- tlv_data->fup_rssi = ev_fup->fup_rssi;
- ret = memcpy_s(&tlv_data->remote_nmi, ETHER_ADDR_LEN,
- &ev_fup->remote_addr, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy remote nmi\n"));
- goto fail;
- }
- WL_TRACE(("local id: %d\n", ev_fup->local_id));
- WL_TRACE(("remote id: %d\n", ev_fup->remote_id));
- WL_TRACE(("peer mac addr: " MACDBG "\n",
- MAC2STRDBG(ev_fup->remote_addr.octet)));
- WL_TRACE(("peer rssi: %d\n", (int8)ev_fup->fup_rssi));
- WL_TRACE(("attribute no: %d\n", ev_fup->attr_num));
- WL_TRACE(("attribute len: %d\n", ev_fup->attr_list_len));
- /* advance to the service descriptor which is attr_list[0] */
- offset = OFFSETOF(wl_nan_ev_receive_t, attr_list[0]);
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- iter = ev_fup->attr_num;
- while (iter) {
- if ((uint8)*p_attr == NAN_ATTR_SVC_DESCRIPTOR) {
- WL_TRACE(("> attr id: 0x%02x\n", (uint8)*p_attr));
- ret = wl_cfgnan_parse_sda_data(osh, p_attr, len, tlv_data);
- if (unlikely(ret)) {
- WL_ERR(("wl_cfgnan_parse_sda_data failed,"
- "error = %d \n", ret));
- goto fail;
- }
- }
- if ((uint8)*p_attr == NAN_ATTR_SVC_DESC_EXTENSION) {
- WL_TRACE(("> attr id: 0x%02x\n", (uint8)*p_attr));
- ret = wl_cfgnan_parse_sdea_data(osh, p_attr, len, tlv_data);
- if (unlikely(ret)) {
- WL_ERR(("wl_cfgnan_parse_sdea_data failed,"
- "error = %d \n", ret));
- goto fail;
- }
- }
- offset = (sizeof(*p_attr) +
- sizeof(ev_fup->attr_list_len) +
- (p_attr[1] | (p_attr[2] << 8)));
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- iter--;
- }
- } else if (type == WL_NAN_XTLV_SD_SDF_RX) {
- /*
- * SDF followed by nan2_pub_act_frame_t and wifi_nan_svc_descriptor_attr_t,
- * and svc controls are optional.
- */
- const nan2_pub_act_frame_t *nan_pub_af =
- (const nan2_pub_act_frame_t *)p_attr;
- WL_TRACE((">> WL_NAN_XTLV_SD_SDF_RX\n"));
- /* nan2_pub_act_frame_t */
- WL_TRACE(("pub category: 0x%02x\n", nan_pub_af->category_id));
- WL_TRACE(("pub action: 0x%02x\n", nan_pub_af->action_field));
- WL_TRACE(("nan oui: %2x-%2x-%2x\n",
- nan_pub_af->oui[0], nan_pub_af->oui[1], nan_pub_af->oui[2]));
- WL_TRACE(("oui type: 0x%02x\n", nan_pub_af->oui_type));
- WL_TRACE(("oui subtype: 0x%02x\n", nan_pub_af->oui_sub_type));
- offset = sizeof(*nan_pub_af);
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- } else if (type == WL_NAN_XTLV_SD_REPLIED) {
- ev_replied = (const wl_nan_event_replied_t *)p_attr;
- WL_TRACE((">> WL_NAN_XTLV_SD_REPLIED: Replied Event\n"));
- tlv_data->pub_id = (wl_nan_instance_id_t)ev_replied->pub_id;
- tlv_data->sub_id = (wl_nan_instance_id_t)ev_replied->sub_id;
- tlv_data->sub_rssi = ev_replied->sub_rssi;
- ret = memcpy_s(&tlv_data->remote_nmi, ETHER_ADDR_LEN,
- &ev_replied->sub_mac, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy remote nmi\n"));
- goto fail;
- }
- WL_TRACE(("publish id: %d\n", ev_replied->pub_id));
- WL_TRACE(("subscribe d: %d\n", ev_replied->sub_id));
- WL_TRACE(("Subscriber mac addr: " MACDBG "\n",
- MAC2STRDBG(ev_replied->sub_mac.octet)));
- WL_TRACE(("subscribe rssi: %d\n", (int8)ev_replied->sub_rssi));
- WL_TRACE(("attribute no: %d\n", ev_replied->attr_num));
- WL_TRACE(("attribute len: %d\n", (uint16)ev_replied->attr_list_len));
- /* advance to the service descriptor which is attr_list[0] */
- offset = OFFSETOF(wl_nan_event_replied_t, attr_list[0]);
- if (offset > len) {
- WL_ERR(("Invalid event buffer len\n"));
- ret = BCME_BUFTOOSHORT;
- goto fail;
- }
- p_attr += offset;
- len -= offset;
- ret = wl_cfgnan_parse_sda_data(osh, p_attr, len, tlv_data);
- if (unlikely(ret)) {
- WL_ERR(("wl_cfgnan_parse_sdea_data failed,"
- "error = %d \n", ret));
- }
- }
- fail:
- return ret;
- }
- /* Based on each case of tlv type id, fill into tlv data */
- int
- wl_cfgnan_set_vars_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
- {
- nan_parse_event_ctx_t *ctx_tlv_data = ((nan_parse_event_ctx_t *)(ctx));
- nan_event_data_t *tlv_data = ((nan_event_data_t *)(ctx_tlv_data->nan_evt_data));
- int ret = BCME_OK;
- NAN_DBG_ENTER();
- if (!data || !len) {
- WL_ERR(("data length is invalid\n"));
- ret = BCME_ERROR;
- goto fail;
- }
- switch (type) {
- /*
- * Need to parse service descript attributes including service control,
- * when Follow up or Discovery result come
- */
- case WL_NAN_XTLV_SD_FUP_RECEIVED:
- case WL_NAN_XTLV_SD_DISC_RESULTS: {
- ret = wl_cfgnan_parse_sd_attr_data(ctx_tlv_data->cfg->osh,
- len, data, tlv_data, type);
- break;
- }
- case WL_NAN_XTLV_SD_SVC_INFO: {
- tlv_data->svc_info.data =
- MALLOCZ(ctx_tlv_data->cfg->osh, len);
- if (!tlv_data->svc_info.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- tlv_data->svc_info.dlen = 0;
- ret = BCME_NOMEM;
- goto fail;
- }
- tlv_data->svc_info.dlen = len;
- ret = memcpy_s(tlv_data->svc_info.data, tlv_data->svc_info.dlen,
- data, tlv_data->svc_info.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy svc info data\n"));
- goto fail;
- }
- break;
- }
- default:
- WL_ERR(("Not available for tlv type = 0x%x\n", type));
- ret = BCME_ERROR;
- break;
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfg_nan_check_cmd_len(uint16 nan_iov_len, uint16 data_size,
- uint16 *subcmd_len)
- {
- s32 ret = BCME_OK;
- if (subcmd_len != NULL) {
- *subcmd_len = OFFSETOF(bcm_iov_batch_subcmd_t, data) +
- ALIGN_SIZE(data_size, 4);
- if (*subcmd_len > nan_iov_len) {
- WL_ERR(("%s: Buf short, requested:%d, available:%d\n",
- __FUNCTION__, *subcmd_len, nan_iov_len));
- ret = BCME_NOMEM;
- }
- } else {
- WL_ERR(("Invalid subcmd_len\n"));
- ret = BCME_ERROR;
- }
- return ret;
- }
- int
- wl_cfgnan_config_eventmask(struct net_device *ndev, struct bcm_cfg80211 *cfg,
- uint8 event_ind_flag, bool disable_events)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint16 subcmd_len;
- uint32 status;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd_resp = NULL;
- uint8 event_mask[WL_NAN_EVMASK_EXTN_LEN];
- wl_nan_evmask_extn_t *evmask;
- uint16 evmask_cmd_len;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- NAN_DBG_ENTER();
- /* same src and dest len here */
- (void)memset_s(event_mask, WL_NAN_EVMASK_EXTN_VER, 0, WL_NAN_EVMASK_EXTN_VER);
- evmask_cmd_len = OFFSETOF(wl_nan_evmask_extn_t, evmask) +
- WL_NAN_EVMASK_EXTN_LEN;
- ret = wl_add_remove_eventmsg(ndev, WLC_E_NAN, true);
- if (unlikely(ret)) {
- WL_ERR((" nan event enable failed, error = %d \n", ret));
- goto fail;
- }
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(uint8 *)(&nan_buf->cmds[0]);
- ret = wl_cfg_nan_check_cmd_len(nan_buf_size,
- evmask_cmd_len, &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_EVENT_MASK);
- sub_cmd->len = sizeof(sub_cmd->u.options) + evmask_cmd_len;
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- evmask = (wl_nan_evmask_extn_t *)sub_cmd->data;
- evmask->ver = WL_NAN_EVMASK_EXTN_VER;
- evmask->len = WL_NAN_EVMASK_EXTN_LEN;
- nan_buf_size -= subcmd_len;
- nan_buf->count = 1;
- if (disable_events) {
- WL_DBG(("Disabling all nan events..except stop event\n"));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_STOP));
- } else {
- /*
- * Android framework event mask configuration.
- */
- nan_buf->is_set = false;
- memset(resp_buf, 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("get nan event mask failed ret %d status %d \n",
- ret, status));
- goto fail;
- }
- sub_cmd_resp = &((bcm_iov_batch_buf_t *)(resp_buf))->cmds[0];
- evmask = (wl_nan_evmask_extn_t *)sub_cmd_resp->data;
- /* check the response buff */
- /* same src and dest len here */
- (void)memcpy_s(&event_mask, WL_NAN_EVMASK_EXTN_LEN,
- (uint8*)&evmask->evmask, WL_NAN_EVMASK_EXTN_LEN);
- if (event_ind_flag) {
- if (CHECK_BIT(event_ind_flag, WL_NAN_EVENT_DIC_MAC_ADDR_BIT)) {
- WL_DBG(("Need to add disc mac addr change event\n"));
- }
- /* BIT2 - Disable nan cluster join indication (OTA). */
- if (CHECK_BIT(event_ind_flag, WL_NAN_EVENT_JOIN_EVENT)) {
- clrbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_MERGE));
- }
- }
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_DISCOVERY_RESULT));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_RECEIVE));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_TERMINATED));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_STOP));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_TXS));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_PEER_DATAPATH_IND));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_DATAPATH_ESTB));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_DATAPATH_END));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_RNG_REQ_IND));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_RNG_TERM_IND));
- setbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_DISC_CACHE_TIMEOUT));
- /* Disable below events by default */
- clrbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_PEER_SCHED_UPD_NOTIF));
- clrbit(event_mask, NAN_EVENT_MAP(WL_NAN_EVENT_RNG_RPT_IND));
- }
- nan_buf->is_set = true;
- evmask = (wl_nan_evmask_extn_t *)sub_cmd->data;
- /* same src and dest len here */
- (void)memcpy_s((uint8*)&evmask->evmask, WL_NAN_EVMASK_EXTN_LEN,
- &event_mask, WL_NAN_EVMASK_EXTN_LEN);
- nan_buf_size = (NAN_IOCTL_BUF_SIZE - nan_buf_size);
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("set nan event mask failed ret %d status %d \n", ret, status));
- goto fail;
- }
- WL_DBG(("set nan event mask successfull\n"));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_nan_avail(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_avail_cmd_data *cmd_data, uint8 avail_type)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint16 subcmd_len;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_iov_t *nan_iov_data = NULL;
- wl_avail_t *avail = NULL;
- wl_avail_entry_t *entry; /* used for filling entry structure */
- uint8 *p; /* tracking pointer */
- uint8 i;
- u32 status;
- int c;
- char ndc_id[ETHER_ADDR_LEN] = { 0x50, 0x6f, 0x9a, 0x01, 0x0, 0x0 };
- dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(ndev);
- char *a = WL_AVAIL_BIT_MAP;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- NAN_DBG_ENTER();
- /* Do not disturb avail if dam is supported */
- if (FW_SUPPORTED(dhdp, autodam)) {
- WL_DBG(("DAM is supported, avail modification not allowed\n"));
- return ret;
- }
- if (avail_type < WL_AVAIL_LOCAL || avail_type > WL_AVAIL_TYPE_MAX) {
- WL_ERR(("Invalid availability type\n"));
- ret = BCME_USAGE_ERROR;
- goto fail;
- }
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data = MALLOCZ(cfg->osh, sizeof(*nan_iov_data));
- if (!nan_iov_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data->nan_iov_len = NAN_IOCTL_BUF_SIZE;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*avail), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- avail = (wl_avail_t *)sub_cmd->data;
- /* populate wl_avail_type */
- avail->flags = avail_type;
- if (avail_type == WL_AVAIL_RANGING) {
- ret = memcpy_s(&avail->addr, ETHER_ADDR_LEN,
- &cmd_data->peer_nmi, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy peer nmi\n"));
- goto fail;
- }
- }
- sub_cmd->len = sizeof(sub_cmd->u.options) + subcmd_len;
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_AVAIL);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_buf->is_set = false;
- nan_buf->count++;
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_buf_size = (NAN_IOCTL_BUF_SIZE - nan_iov_data->nan_iov_len);
- WL_TRACE(("Read wl nan avail status\n"));
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret)) {
- WL_ERR(("\n Get nan avail failed ret %d, status %d \n", ret, status));
- goto fail;
- }
- if (status == BCME_NOTFOUND) {
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- avail = (wl_avail_t *)sub_cmd->data;
- p = avail->entry;
- /* populate wl_avail fields */
- avail->length = OFFSETOF(wl_avail_t, entry);
- avail->flags = avail_type;
- avail->num_entries = 0;
- avail->id = 0;
- entry = (wl_avail_entry_t*)p;
- entry->flags = WL_AVAIL_ENTRY_COM;
- /* set default values for optional parameters */
- entry->start_offset = 0;
- entry->u.band = 0;
- if (cmd_data->avail_period) {
- entry->period = cmd_data->avail_period;
- } else {
- entry->period = WL_AVAIL_PERIOD_1024;
- }
- if (cmd_data->duration != NAN_BAND_INVALID) {
- entry->flags |= (3 << WL_AVAIL_ENTRY_USAGE_SHIFT) |
- (cmd_data->duration << WL_AVAIL_ENTRY_BIT_DUR_SHIFT);
- } else {
- entry->flags |= (3 << WL_AVAIL_ENTRY_USAGE_SHIFT) |
- (WL_AVAIL_BIT_DUR_16 << WL_AVAIL_ENTRY_BIT_DUR_SHIFT);
- }
- entry->bitmap_len = 0;
- if (avail_type == WL_AVAIL_LOCAL) {
- entry->flags |= 1 << WL_AVAIL_ENTRY_CHAN_SHIFT;
- /* Check for 5g support, based on that choose 5g channel */
- if (cfg->support_5g) {
- entry->u.channel_info =
- htod32(wf_channel2chspec(WL_AVAIL_CHANNEL_5G,
- WL_AVAIL_BANDWIDTH_5G));
- } else {
- entry->u.channel_info =
- htod32(wf_channel2chspec(WL_AVAIL_CHANNEL_2G,
- WL_AVAIL_BANDWIDTH_2G));
- }
- entry->flags = htod16(entry->flags);
- }
- if (cfg->support_5g) {
- a = WL_5G_AVAIL_BIT_MAP;
- }
- /* point to bitmap value for processing */
- if (cmd_data->bmap) {
- for (c = (WL_NAN_EVENT_CLEAR_BIT-1); c >= 0; c--) {
- i = cmd_data->bmap >> c;
- if (i & 1) {
- setbit(entry->bitmap, (WL_NAN_EVENT_CLEAR_BIT-c-1));
- }
- }
- } else {
- for (i = 0; i < strlen(WL_AVAIL_BIT_MAP); i++) {
- if (*a == '1') {
- setbit(entry->bitmap, i);
- }
- a++;
- }
- }
- /* account for partially filled most significant byte */
- entry->bitmap_len = ((WL_NAN_EVENT_CLEAR_BIT) + NBBY - 1) / NBBY;
- if (avail_type == WL_AVAIL_NDC) {
- ret = memcpy_s(&avail->addr, ETHER_ADDR_LEN,
- ndc_id, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy ndc id\n"));
- goto fail;
- }
- } else if (avail_type == WL_AVAIL_RANGING) {
- ret = memcpy_s(&avail->addr, ETHER_ADDR_LEN,
- &cmd_data->peer_nmi, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy peer nmi\n"));
- goto fail;
- }
- }
- /* account for partially filled most significant byte */
- /* update wl_avail and populate wl_avail_entry */
- entry->length = OFFSETOF(wl_avail_entry_t, bitmap) + entry->bitmap_len;
- avail->num_entries++;
- avail->length += entry->length;
- /* advance pointer for next entry */
- p += entry->length;
- /* convert to dongle endianness */
- entry->length = htod16(entry->length);
- entry->start_offset = htod16(entry->start_offset);
- entry->u.channel_info = htod32(entry->u.channel_info);
- entry->flags = htod16(entry->flags);
- /* update avail_len only if
- * there are avail entries
- */
- if (avail->num_entries) {
- nan_iov_data->nan_iov_len -= avail->length;
- avail->length = htod16(avail->length);
- avail->flags = htod16(avail->flags);
- }
- avail->length = htod16(avail->length);
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_AVAIL);
- sub_cmd->len = sizeof(sub_cmd->u.options) + avail->length;
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_buf->is_set = true;
- nan_buf->count++;
- /* Reduce the iov_len size by subcmd_len */
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_buf_size = (NAN_IOCTL_BUF_SIZE - nan_iov_data->nan_iov_len);
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("\n set nan avail failed ret %d status %d \n", ret, status));
- ret = status;
- goto fail;
- }
- } else if (status == BCME_OK) {
- WL_DBG(("Avail type [%d] found to be configured\n", avail_type));
- } else {
- WL_ERR(("set nan avail failed ret %d status %d \n", ret, status));
- }
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- if (nan_iov_data) {
- MFREE(cfg->osh, nan_iov_data, sizeof(*nan_iov_data));
- }
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_config_control_flag(struct net_device *ndev, struct bcm_cfg80211 *cfg,
- uint32 flag, uint32 *status, bool set)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_iov_start, nan_iov_end;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint16 subcmd_len;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd_resp = NULL;
- wl_nan_iov_t *nan_iov_data = NULL;
- uint32 cfg_ctrl;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- NAN_DBG_ENTER();
- WL_INFORM_MEM(("%s: Modifying nan ctrl flag %x val %d",
- __FUNCTION__, flag, set));
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data = MALLOCZ(cfg->osh, sizeof(*nan_iov_data));
- if (!nan_iov_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data->nan_iov_len = nan_iov_start = NAN_IOCTL_BUF_SIZE;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(cfg_ctrl), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_NAN_CONFIG);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(cfg_ctrl);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_buf->is_set = false;
- nan_buf->count++;
- /* Reduce the iov_len size by subcmd_len */
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_end = nan_iov_data->nan_iov_len;
- nan_buf_size = (nan_iov_start - nan_iov_end);
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(*status)) {
- WL_ERR(("get nan cfg ctrl failed ret %d status %d \n", ret, *status));
- goto fail;
- }
- sub_cmd_resp = &((bcm_iov_batch_buf_t *)(resp_buf))->cmds[0];
- /* check the response buff */
- cfg_ctrl = (*(uint32 *)&sub_cmd_resp->data[0]);
- if (set) {
- cfg_ctrl |= flag;
- } else {
- cfg_ctrl &= ~flag;
- }
- ret = memcpy_s(sub_cmd->data, sizeof(cfg_ctrl),
- &cfg_ctrl, sizeof(cfg_ctrl));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy cfg ctrl\n"));
- goto fail;
- }
- nan_buf->is_set = true;
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(*status)) {
- WL_ERR(("set nan cfg ctrl failed ret %d status %d \n", ret, *status));
- goto fail;
- }
- WL_DBG(("set nan cfg ctrl successfull\n"));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- if (nan_iov_data) {
- MFREE(cfg->osh, nan_iov_data, sizeof(*nan_iov_data));
- }
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_get_iovars_status(void *ctx, const uint8 *data, uint16 type, uint16 len)
- {
- bcm_iov_batch_buf_t *b_resp = (bcm_iov_batch_buf_t *)ctx;
- uint32 status;
- /* if all tlvs are parsed, we should not be here */
- if (b_resp->count == 0) {
- return BCME_BADLEN;
- }
- /* cbfn params may be used in f/w */
- if (len < sizeof(status)) {
- return BCME_BUFTOOSHORT;
- }
- /* first 4 bytes consists status */
- if (memcpy_s(&status, sizeof(status),
- data, sizeof(uint32)) != BCME_OK) {
- WL_ERR(("Failed to copy status\n"));
- goto exit;
- }
- status = dtoh32(status);
- /* If status is non zero */
- if (status != BCME_OK) {
- printf("cmd type %d failed, status: %04x\n", type, status);
- goto exit;
- }
- if (b_resp->count > 0) {
- b_resp->count--;
- }
- if (!b_resp->count) {
- status = BCME_IOV_LAST_CMD;
- }
- exit:
- return status;
- }
- static int
- wl_cfgnan_execute_ioctl(struct net_device *ndev, struct bcm_cfg80211 *cfg,
- bcm_iov_batch_buf_t *nan_buf, uint16 nan_buf_size, uint32 *status,
- uint8 *resp_buf, uint16 resp_buf_size)
- {
- int ret = BCME_OK;
- uint16 tlvs_len;
- int res = BCME_OK;
- bcm_iov_batch_buf_t *p_resp = NULL;
- char *iov = "nan";
- int max_resp_len = WLC_IOCTL_MAXLEN;
- WL_DBG(("Enter:\n"));
- if (nan_buf->is_set) {
- ret = wldev_iovar_setbuf(ndev, "nan", nan_buf, nan_buf_size,
- resp_buf, resp_buf_size, NULL);
- p_resp = (bcm_iov_batch_buf_t *)(resp_buf + strlen(iov) + 1);
- } else {
- ret = wldev_iovar_getbuf(ndev, "nan", nan_buf, nan_buf_size,
- resp_buf, resp_buf_size, NULL);
- p_resp = (bcm_iov_batch_buf_t *)(resp_buf);
- }
- if (unlikely(ret)) {
- WL_ERR((" nan execute ioctl failed, error = %d \n", ret));
- goto fail;
- }
- p_resp->is_set = nan_buf->is_set;
- tlvs_len = max_resp_len - OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- /* Extract the tlvs and print their resp in cb fn */
- res = bcm_unpack_xtlv_buf((void *)p_resp, (const uint8 *)&p_resp->cmds[0],
- tlvs_len, BCM_IOV_CMD_OPT_ALIGN32, wl_cfgnan_get_iovars_status);
- if (res == BCME_IOV_LAST_CMD) {
- res = BCME_OK;
- }
- fail:
- *status = res;
- WL_DBG((" nan ioctl ret %d status %d \n", ret, *status));
- return ret;
- }
- static int
- wl_cfgnan_if_addr_handler(void *p_buf, uint16 *nan_buf_size,
- struct ether_addr *if_addr)
- {
- /* nan enable */
- s32 ret = BCME_OK;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- if (p_buf != NULL) {
- bcm_iov_batch_subcmd_t *sub_cmd = (bcm_iov_batch_subcmd_t*)(p_buf);
- ret = wl_cfg_nan_check_cmd_len(*nan_buf_size,
- sizeof(*if_addr), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- /* Fill the sub_command block */
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_IF_ADDR);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(*if_addr);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- ret = memcpy_s(sub_cmd->data, sizeof(*if_addr),
- (uint8 *)if_addr, sizeof(*if_addr));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy if addr\n"));
- goto fail;
- }
- *nan_buf_size -= subcmd_len;
- } else {
- WL_ERR(("nan_iov_buf is NULL\n"));
- ret = BCME_ERROR;
- goto fail;
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_get_ver(struct net_device *ndev, struct bcm_cfg80211 *cfg)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- wl_nan_ver_t *nan_ver = NULL;
- uint16 subcmd_len;
- uint32 status;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd_resp = NULL;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- NAN_DBG_ENTER();
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(uint8 *)(&nan_buf->cmds[0]);
- ret = wl_cfg_nan_check_cmd_len(nan_buf_size,
- sizeof(*nan_ver), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- nan_ver = (wl_nan_ver_t *)sub_cmd->data;
- sub_cmd->id = htod16(WL_NAN_CMD_GLB_NAN_VER);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(*nan_ver);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_buf_size -= subcmd_len;
- nan_buf->count = 1;
- nan_buf->is_set = false;
- bzero(resp_buf, sizeof(resp_buf));
- nan_buf_size = NAN_IOCTL_BUF_SIZE - nan_buf_size;
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("get nan ver failed ret %d status %d \n",
- ret, status));
- goto fail;
- }
- sub_cmd_resp = &((bcm_iov_batch_buf_t *)(resp_buf))->cmds[0];
- nan_ver = ((wl_nan_ver_t *)&sub_cmd_resp->data[0]);
- if (!nan_ver) {
- ret = BCME_NOTFOUND;
- WL_ERR(("nan_ver not found: err = %d\n", ret));
- goto fail;
- }
- cfg->nancfg.version = *nan_ver;
- WL_INFORM_MEM(("Nan Version is %d\n", cfg->nancfg.version));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_if_addr(struct bcm_cfg80211 *cfg)
- {
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint32 status;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- struct ether_addr if_addr;
- uint8 buf[NAN_IOCTL_BUF_SIZE];
- bcm_iov_batch_buf_t *nan_buf = (bcm_iov_batch_buf_t*)buf;
- bool rand_mac = cfg->nancfg.mac_rand;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- if (rand_mac) {
- RANDOM_BYTES(if_addr.octet, 6);
- /* restore mcast and local admin bits to 0 and 1 */
- ETHER_SET_UNICAST(if_addr.octet);
- ETHER_SET_LOCALADDR(if_addr.octet);
- } else {
- /* Use primary MAC with the locally administered bit for the
- * NAN NMI I/F
- */
- if (wl_get_vif_macaddr(cfg, WL_IF_TYPE_NAN_NMI,
- if_addr.octet) != BCME_OK) {
- ret = -EINVAL;
- WL_ERR(("Failed to get mac addr for NMI\n"));
- goto fail;
- }
- }
- WL_INFORM_MEM(("%s: NMI " MACDBG "\n",
- __FUNCTION__, MAC2STRDBG(if_addr.octet)));
- ret = wl_cfgnan_if_addr_handler(&nan_buf->cmds[0],
- &nan_buf_size, &if_addr);
- if (unlikely(ret)) {
- WL_ERR(("Nan if addr handler sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- nan_buf->is_set = true;
- nan_buf_size = NAN_IOCTL_BUF_SIZE - nan_buf_size;
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(bcmcfg_to_prmry_ndev(cfg), cfg,
- nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("nan if addr handler failed ret %d status %d\n",
- ret, status));
- goto fail;
- }
- ret = memcpy_s(cfg->nan_nmi_mac, ETH_ALEN,
- if_addr.octet, ETH_ALEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nmi addr\n"));
- goto fail;
- }
- return ret;
- fail:
- if (!rand_mac) {
- wl_release_vif_macaddr(cfg, if_addr.octet, WL_IF_TYPE_NAN_NMI);
- }
- return ret;
- }
- static int
- wl_cfgnan_init_handler(void *p_buf, uint16 *nan_buf_size, bool val)
- {
- /* nan enable */
- s32 ret = BCME_OK;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- if (p_buf != NULL) {
- bcm_iov_batch_subcmd_t *sub_cmd = (bcm_iov_batch_subcmd_t*)(p_buf);
- ret = wl_cfg_nan_check_cmd_len(*nan_buf_size,
- sizeof(val), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- /* Fill the sub_command block */
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_NAN_INIT);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(uint8);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- ret = memcpy_s(sub_cmd->data, sizeof(uint8),
- (uint8*)&val, sizeof(uint8));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy init value\n"));
- goto fail;
- }
- *nan_buf_size -= subcmd_len;
- } else {
- WL_ERR(("nan_iov_buf is NULL\n"));
- ret = BCME_ERROR;
- goto fail;
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_enable_handler(wl_nan_iov_t *nan_iov_data, bool val)
- {
- /* nan enable */
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(val), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- /* Fill the sub_command block */
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_NAN_ENAB);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(uint8);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- ret = memcpy_s(sub_cmd->data, sizeof(uint8),
- (uint8*)&val, sizeof(uint8));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy enab value\n"));
- return ret;
- }
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_warmup_time_handler(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data)
- {
- /* wl nan warm_up_time */
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_warmup_time_ticks_t *wup_ticks = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- wup_ticks = (wl_nan_warmup_time_ticks_t *)sub_cmd->data;
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*wup_ticks), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- /* Fill the sub_command block */
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_WARMUP_TIME);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- sizeof(*wup_ticks);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- *wup_ticks = cmd_data->warmup_time;
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_election_metric(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data, uint32 nan_attr_mask)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_election_metric_config_t *metrics = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd =
- (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*metrics), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- metrics = (wl_nan_election_metric_config_t *)sub_cmd->data;
- if (nan_attr_mask & NAN_ATTR_RAND_FACTOR_CONFIG) {
- metrics->random_factor = (uint8)cmd_data->metrics.random_factor;
- }
- if ((!cmd_data->metrics.master_pref) ||
- (cmd_data->metrics.master_pref > NAN_MAXIMUM_MASTER_PREFERENCE)) {
- WL_TRACE(("Master Pref is 0 or greater than 254, hence sending random value\n"));
- /* Master pref for mobile devices can be from 1 - 127 as per Spec AppendixC */
- metrics->master_pref = (RANDOM32()%(NAN_MAXIMUM_MASTER_PREFERENCE/2)) + 1;
- } else {
- metrics->master_pref = (uint8)cmd_data->metrics.master_pref;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_ELECTION_METRICS_CONFIG);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- sizeof(*metrics);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_rssi_proximity(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data, uint32 nan_attr_mask)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_rssi_notif_thld_t *rssi_notif_thld = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- rssi_notif_thld = (wl_nan_rssi_notif_thld_t *)sub_cmd->data;
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*rssi_notif_thld), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- if (nan_attr_mask & NAN_ATTR_RSSI_PROXIMITY_2G_CONFIG) {
- rssi_notif_thld->bcn_rssi_2g =
- cmd_data->rssi_attr.rssi_proximity_2dot4g_val;
- } else {
- /* Keeping RSSI threshold value to be -70dBm */
- rssi_notif_thld->bcn_rssi_2g = NAN_DEF_RSSI_NOTIF_THRESH;
- }
- if (nan_attr_mask & NAN_ATTR_RSSI_PROXIMITY_5G_CONFIG) {
- rssi_notif_thld->bcn_rssi_5g =
- cmd_data->rssi_attr.rssi_proximity_5g_val;
- } else {
- /* Keeping RSSI threshold value to be -70dBm */
- rssi_notif_thld->bcn_rssi_5g = NAN_DEF_RSSI_NOTIF_THRESH;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_SYNC_BCN_RSSI_NOTIF_THRESHOLD);
- sub_cmd->len = htod16(sizeof(sub_cmd->u.options) + sizeof(*rssi_notif_thld));
- sub_cmd->u.options = htod32(BCM_XTLV_OPTION_ALIGN32);
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_rssi_mid_or_close(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data, uint32 nan_attr_mask)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_rssi_thld_t *rssi_thld = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- rssi_thld = (wl_nan_rssi_thld_t *)sub_cmd->data;
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*rssi_thld), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- /*
- * Keeping RSSI mid value -75dBm for both 2G and 5G
- * Keeping RSSI close value -60dBm for both 2G and 5G
- */
- if (nan_attr_mask & NAN_ATTR_RSSI_MIDDLE_2G_CONFIG) {
- rssi_thld->rssi_mid_2g =
- cmd_data->rssi_attr.rssi_middle_2dot4g_val;
- } else {
- rssi_thld->rssi_mid_2g = NAN_DEF_RSSI_MID;
- }
- if (nan_attr_mask & NAN_ATTR_RSSI_MIDDLE_5G_CONFIG) {
- rssi_thld->rssi_mid_5g =
- cmd_data->rssi_attr.rssi_middle_5g_val;
- } else {
- rssi_thld->rssi_mid_5g = NAN_DEF_RSSI_MID;
- }
- if (nan_attr_mask & NAN_ATTR_RSSI_CLOSE_CONFIG) {
- rssi_thld->rssi_close_2g =
- cmd_data->rssi_attr.rssi_close_2dot4g_val;
- } else {
- rssi_thld->rssi_close_2g = NAN_DEF_RSSI_CLOSE;
- }
- if (nan_attr_mask & NAN_ATTR_RSSI_CLOSE_5G_CONFIG) {
- rssi_thld->rssi_close_5g =
- cmd_data->rssi_attr.rssi_close_5g_val;
- } else {
- rssi_thld->rssi_close_5g = NAN_DEF_RSSI_CLOSE;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_ELECTION_RSSI_THRESHOLD);
- sub_cmd->len = htod16(sizeof(sub_cmd->u.options) + sizeof(*rssi_thld));
- sub_cmd->u.options = htod32(BCM_XTLV_OPTION_ALIGN32);
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- check_for_valid_5gchan(struct net_device *ndev, uint8 chan)
- {
- s32 ret = BCME_OK;
- uint bitmap;
- u8 ioctl_buf[WLC_IOCTL_SMLEN];
- uint32 chanspec_arg;
- NAN_DBG_ENTER();
- chanspec_arg = CH20MHZ_CHSPEC(chan);
- chanspec_arg = wl_chspec_host_to_driver(chanspec_arg);
- memset_s(ioctl_buf, WLC_IOCTL_SMLEN, 0, WLC_IOCTL_SMLEN);
- ret = wldev_iovar_getbuf(ndev, "per_chan_info",
- (void *)&chanspec_arg, sizeof(chanspec_arg),
- ioctl_buf, WLC_IOCTL_SMLEN, NULL);
- if (ret != BCME_OK) {
- WL_ERR(("Chaninfo for channel = %d, error %d\n", chan, ret));
- goto exit;
- }
- bitmap = dtoh32(*(uint *)ioctl_buf);
- if (!(bitmap & WL_CHAN_VALID_HW)) {
- WL_ERR(("Invalid channel\n"));
- ret = BCME_BADCHAN;
- goto exit;
- }
- if (!(bitmap & WL_CHAN_VALID_SW)) {
- WL_ERR(("Not supported in current locale\n"));
- ret = BCME_BADCHAN;
- goto exit;
- }
- exit:
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_nan_soc_chans(struct net_device *ndev, nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data, uint32 nan_attr_mask)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_social_channels_t *soc_chans = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- soc_chans =
- (wl_nan_social_channels_t *)sub_cmd->data;
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*soc_chans), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_SYNC_SOCIAL_CHAN);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- sizeof(*soc_chans);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- if (nan_attr_mask & NAN_ATTR_2G_CHAN_CONFIG) {
- soc_chans->soc_chan_2g = cmd_data->chanspec[1];
- } else {
- soc_chans->soc_chan_2g = NAN_DEF_SOCIAL_CHAN_2G;
- }
- if (cmd_data->support_5g) {
- if (nan_attr_mask & NAN_ATTR_5G_CHAN_CONFIG) {
- soc_chans->soc_chan_5g = cmd_data->chanspec[2];
- } else {
- soc_chans->soc_chan_5g = NAN_DEF_SOCIAL_CHAN_5G;
- }
- ret = check_for_valid_5gchan(ndev, soc_chans->soc_chan_5g);
- if (ret != BCME_OK) {
- ret = check_for_valid_5gchan(ndev, NAN_DEF_SEC_SOCIAL_CHAN_5G);
- if (ret == BCME_OK) {
- soc_chans->soc_chan_5g = NAN_DEF_SEC_SOCIAL_CHAN_5G;
- } else {
- soc_chans->soc_chan_5g = 0;
- ret = BCME_OK;
- WL_ERR(("Current locale doesn't support 5G op"
- "continuing with 2G only operation\n"));
- }
- }
- } else {
- WL_DBG(("5G support is disabled\n"));
- }
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_nan_scan_params(struct net_device *ndev, struct bcm_cfg80211 *cfg,
- nan_config_cmd_data_t *cmd_data, uint8 band_index, uint32 nan_attr_mask)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_iov_start, nan_iov_end;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint16 subcmd_len;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_iov_t *nan_iov_data = NULL;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- wl_nan_scan_params_t *scan_params = NULL;
- uint32 status;
- NAN_DBG_ENTER();
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data = MALLOCZ(cfg->osh, sizeof(*nan_iov_data));
- if (!nan_iov_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data->nan_iov_len = nan_iov_start = NAN_IOCTL_BUF_SIZE;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*scan_params), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- scan_params = (wl_nan_scan_params_t *)sub_cmd->data;
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_SCAN_PARAMS);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(*scan_params);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- if (!band_index) {
- /* Fw default: Dwell time for 2G is 210 */
- if ((nan_attr_mask & NAN_ATTR_2G_DWELL_TIME_CONFIG) &&
- cmd_data->dwell_time[0]) {
- scan_params->dwell_time = cmd_data->dwell_time[0] +
- NAN_SCAN_DWELL_TIME_DELTA_MS;
- }
- /* Fw default: Scan period for 2G is 10 */
- if (nan_attr_mask & NAN_ATTR_2G_SCAN_PERIOD_CONFIG) {
- scan_params->scan_period = cmd_data->scan_period[0];
- }
- } else {
- if ((nan_attr_mask & NAN_ATTR_5G_DWELL_TIME_CONFIG) &&
- cmd_data->dwell_time[1]) {
- scan_params->dwell_time = cmd_data->dwell_time[1] +
- NAN_SCAN_DWELL_TIME_DELTA_MS;
- }
- if (nan_attr_mask & NAN_ATTR_5G_SCAN_PERIOD_CONFIG) {
- scan_params->scan_period = cmd_data->scan_period[1];
- }
- }
- scan_params->band_index = band_index;
- nan_buf->is_set = true;
- nan_buf->count++;
- /* Reduce the iov_len size by subcmd_len */
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_end = nan_iov_data->nan_iov_len;
- nan_buf_size = (nan_iov_start - nan_iov_end);
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("set nan scan params failed ret %d status %d \n", ret, status));
- goto fail;
- }
- WL_DBG(("set nan scan params successfull\n"));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- if (nan_iov_data) {
- MFREE(cfg->osh, nan_iov_data, sizeof(*nan_iov_data));
- }
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_cluster_id(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- (sizeof(cmd_data->clus_id) - sizeof(uint8)), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- cmd_data->clus_id.octet[0] = 0x50;
- cmd_data->clus_id.octet[1] = 0x6F;
- cmd_data->clus_id.octet[2] = 0x9A;
- cmd_data->clus_id.octet[3] = 0x01;
- WL_TRACE(("cluster_id = " MACDBG "\n", MAC2STRDBG(cmd_data->clus_id.octet)));
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_CID);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(cmd_data->clus_id);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- ret = memcpy_s(sub_cmd->data, sizeof(cmd_data->clus_id),
- (uint8 *)&cmd_data->clus_id,
- sizeof(cmd_data->clus_id));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy clus id\n"));
- return ret;
- }
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_hop_count_limit(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_hop_count_t *hop_limit = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- hop_limit = (wl_nan_hop_count_t *)sub_cmd->data;
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*hop_limit), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- *hop_limit = cmd_data->hop_count_limit;
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_HOP_LIMIT);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(*hop_limit);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_sid_beacon_val(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data, uint32 nan_attr_mask)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_sid_beacon_control_t *sid_beacon = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*sid_beacon), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- sid_beacon = (wl_nan_sid_beacon_control_t *)sub_cmd->data;
- sid_beacon->sid_enable = cmd_data->sid_beacon.sid_enable;
- /* Need to have separate flag for sub beacons
- * sid_beacon->sub_sid_enable = cmd_data->sid_beacon.sub_sid_enable;
- */
- if (nan_attr_mask & NAN_ATTR_SID_BEACON_CONFIG) {
- /* Limit for number of publish SIDs to be included in Beacons */
- sid_beacon->sid_count = cmd_data->sid_beacon.sid_count;
- }
- if (nan_attr_mask & NAN_ATTR_SUB_SID_BEACON_CONFIG) {
- /* Limit for number of subscribe SIDs to be included in Beacons */
- sid_beacon->sub_sid_count = cmd_data->sid_beacon.sub_sid_count;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_SID_BEACON);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- sizeof(*sid_beacon);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_nan_oui(nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(cmd_data->nan_oui), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_CFG_OUI);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(cmd_data->nan_oui);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- ret = memcpy_s(sub_cmd->data, sizeof(cmd_data->nan_oui),
- (uint32 *)&cmd_data->nan_oui,
- sizeof(cmd_data->nan_oui));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nan oui\n"));
- return ret;
- }
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_set_awake_dws(struct net_device *ndev, nan_config_cmd_data_t *cmd_data,
- wl_nan_iov_t *nan_iov_data, struct bcm_cfg80211 *cfg, uint32 nan_attr_mask)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_awake_dws_t *awake_dws = NULL;
- uint16 subcmd_len;
- NAN_DBG_ENTER();
- sub_cmd =
- (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- sizeof(*awake_dws), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- return ret;
- }
- awake_dws = (wl_nan_awake_dws_t *)sub_cmd->data;
- if (nan_attr_mask & NAN_ATTR_2G_DW_CONFIG) {
- awake_dws->dw_interval_2g = cmd_data->awake_dws.dw_interval_2g;
- if (!awake_dws->dw_interval_2g) {
- /* Set 2G awake dw value to fw default value 1 */
- awake_dws->dw_interval_2g = NAN_SYNC_DEF_AWAKE_DW;
- }
- } else {
- /* Set 2G awake dw value to fw default value 1 */
- awake_dws->dw_interval_2g = NAN_SYNC_DEF_AWAKE_DW;
- }
- if (cfg->support_5g) {
- if (nan_attr_mask & NAN_ATTR_5G_DW_CONFIG) {
- awake_dws->dw_interval_5g = cmd_data->awake_dws.dw_interval_5g;
- if (!awake_dws->dw_interval_5g) {
- /* disable 5g beacon ctrls */
- ret = wl_cfgnan_config_control_flag(ndev, cfg,
- WL_NAN_CTRL_DISC_BEACON_TX_5G,
- &(cmd_data->status), 0);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan control set config handler,"
- " ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- ret = wl_cfgnan_config_control_flag(ndev, cfg,
- WL_NAN_CTRL_SYNC_BEACON_TX_5G,
- &(cmd_data->status), 0);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan control set config handler,"
- " ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- }
- } else {
- /* Set 5G awake dw value to fw default value 1 */
- awake_dws->dw_interval_5g = NAN_SYNC_DEF_AWAKE_DW;
- }
- }
- sub_cmd->id = htod16(WL_NAN_CMD_SYNC_AWAKE_DWS);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- sizeof(*awake_dws);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_data->nan_iov_buf += subcmd_len;
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_start_handler(struct net_device *ndev, struct bcm_cfg80211 *cfg,
- nan_config_cmd_data_t *cmd_data, uint32 nan_attr_mask)
- {
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- bcm_iov_batch_buf_t *nan_buf = NULL;
- wl_nan_iov_t *nan_iov_data = NULL;
- dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(ndev);
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- int i;
- s32 timeout = 0;
- nan_hal_capabilities_t capabilities;
- NAN_DBG_ENTER();
- /* Protect discovery creation. Ensure proper mutex precedence.
- * If if_sync & nan_mutex comes together in same context, nan_mutex
- * should follow if_sync.
- */
- mutex_lock(&cfg->if_sync);
- NAN_MUTEX_LOCK();
- #ifdef WL_IFACE_MGMT
- if ((ret = wl_cfg80211_handle_if_role_conflict(cfg, WL_IF_TYPE_NAN_NMI)) != BCME_OK) {
- WL_ERR(("Conflicting iface is present, cant support nan\n"));
- NAN_MUTEX_UNLOCK();
- mutex_unlock(&cfg->if_sync);
- goto fail;
- }
- #endif /* WL_IFACE_MGMT */
- WL_INFORM_MEM(("Initializing NAN\n"));
- ret = wl_cfgnan_init(cfg);
- if (ret != BCME_OK) {
- WL_ERR(("failed to initialize NAN[%d]\n", ret));
- NAN_MUTEX_UNLOCK();
- mutex_unlock(&cfg->if_sync);
- goto fail;
- }
- ret = wl_cfgnan_get_ver(ndev, cfg);
- if (ret != BCME_OK) {
- WL_ERR(("failed to Nan IOV version[%d]\n", ret));
- NAN_MUTEX_UNLOCK();
- mutex_unlock(&cfg->if_sync);
- goto fail;
- }
- /* set nmi addr */
- ret = wl_cfgnan_set_if_addr(cfg);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to set nmi address \n"));
- NAN_MUTEX_UNLOCK();
- mutex_unlock(&cfg->if_sync);
- goto fail;
- }
- cfg->nancfg.nan_event_recvd = false;
- NAN_MUTEX_UNLOCK();
- mutex_unlock(&cfg->if_sync);
- for (i = 0; i < NAN_MAX_NDI; i++) {
- /* Create NDI using the information provided by user space */
- if (cfg->nancfg.ndi[i].in_use && !cfg->nancfg.ndi[i].created) {
- ret = wl_cfgnan_data_path_iface_create_delete_handler(ndev, cfg,
- cfg->nancfg.ndi[i].ifname,
- NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE, dhdp->up);
- if (ret) {
- WL_ERR(("failed to create ndp interface [%d]\n", ret));
- goto fail;
- }
- cfg->nancfg.ndi[i].created = true;
- }
- }
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data = MALLOCZ(cfg->osh, sizeof(*nan_iov_data));
- if (!nan_iov_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data->nan_iov_len = NAN_IOCTL_BUF_SIZE;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- if (nan_attr_mask & NAN_ATTR_SYNC_DISC_2G_BEACON_CONFIG) {
- /* config sync/discovery beacons on 2G band */
- /* 2g is mandatory */
- if (!cmd_data->beacon_2g_val) {
- WL_ERR(("Invalid NAN config...2G is mandatory\n"));
- ret = BCME_BADARG;
- }
- ret = wl_cfgnan_config_control_flag(ndev, cfg,
- WL_NAN_CTRL_DISC_BEACON_TX_2G | WL_NAN_CTRL_SYNC_BEACON_TX_2G,
- &(cmd_data->status), TRUE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan control set config handler, ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- }
- if (nan_attr_mask & NAN_ATTR_SYNC_DISC_5G_BEACON_CONFIG) {
- /* config sync/discovery beacons on 5G band */
- ret = wl_cfgnan_config_control_flag(ndev, cfg,
- WL_NAN_CTRL_DISC_BEACON_TX_5G | WL_NAN_CTRL_SYNC_BEACON_TX_5G,
- &(cmd_data->status), cmd_data->beacon_5g_val);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan control set config handler, ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- }
- /* Setting warm up time */
- cmd_data->warmup_time = 1;
- if (cmd_data->warmup_time) {
- ret = wl_cfgnan_warmup_time_handler(cmd_data, nan_iov_data);
- if (unlikely(ret)) {
- WL_ERR(("warm up time handler sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- }
- /* setting master preference and random factor */
- ret = wl_cfgnan_set_election_metric(cmd_data, nan_iov_data, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("election_metric sub_cmd set failed\n"));
- goto fail;
- } else {
- nan_buf->count++;
- }
- /* setting nan social channels */
- ret = wl_cfgnan_set_nan_soc_chans(ndev, cmd_data, nan_iov_data, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("nan social channels set failed\n"));
- goto fail;
- } else {
- /* Storing 5g capability which is reqd for avail chan config. */
- cfg->support_5g = cmd_data->support_5g;
- nan_buf->count++;
- }
- if ((cmd_data->support_2g) && ((cmd_data->dwell_time[0]) ||
- (cmd_data->scan_period[0]))) {
- /* setting scan params */
- ret = wl_cfgnan_set_nan_scan_params(ndev, cfg, cmd_data, 0, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("scan params set failed for 2g\n"));
- goto fail;
- }
- }
- if ((cmd_data->support_5g) && ((cmd_data->dwell_time[1]) ||
- (cmd_data->scan_period[1]))) {
- /* setting scan params */
- ret = wl_cfgnan_set_nan_scan_params(ndev, cfg, cmd_data,
- cmd_data->support_5g, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("scan params set failed for 5g\n"));
- goto fail;
- }
- }
- /*
- * A cluster_low value matching cluster_high indicates a request
- * to join a cluster with that value.
- * If the requested cluster is not found the
- * device will start its own cluster
- */
- /* For Debug purpose, using clust id compulsion */
- if (!ETHER_ISNULLADDR(&cmd_data->clus_id.octet)) {
- if (cmd_data->clus_id.octet[4] == cmd_data->clus_id.octet[5]) {
- /* device will merge to configured CID only */
- ret = wl_cfgnan_config_control_flag(ndev, cfg,
- WL_NAN_CTRL_MERGE_CONF_CID_ONLY, &(cmd_data->status), true);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan control set config handler, ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- }
- /* setting cluster ID */
- ret = wl_cfgnan_set_cluster_id(cmd_data, nan_iov_data);
- if (unlikely(ret)) {
- WL_ERR(("cluster_id sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- }
- /* setting rssi proximaty values for 2.4GHz and 5GHz */
- ret = wl_cfgnan_set_rssi_proximity(cmd_data, nan_iov_data, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("2.4GHz/5GHz rssi proximity threshold set failed\n"));
- goto fail;
- } else {
- nan_buf->count++;
- }
- /* setting rssi middle/close values for 2.4GHz and 5GHz */
- ret = wl_cfgnan_set_rssi_mid_or_close(cmd_data, nan_iov_data, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("2.4GHz/5GHz rssi middle and close set failed\n"));
- goto fail;
- } else {
- nan_buf->count++;
- }
- /* setting hop count limit or threshold */
- if (nan_attr_mask & NAN_ATTR_HOP_COUNT_LIMIT_CONFIG) {
- ret = wl_cfgnan_set_hop_count_limit(cmd_data, nan_iov_data);
- if (unlikely(ret)) {
- WL_ERR(("hop_count_limit sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- }
- /* setting sid beacon val */
- if ((nan_attr_mask & NAN_ATTR_SID_BEACON_CONFIG) ||
- (nan_attr_mask & NAN_ATTR_SUB_SID_BEACON_CONFIG)) {
- ret = wl_cfgnan_set_sid_beacon_val(cmd_data, nan_iov_data, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("sid_beacon sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- }
- /* setting nan oui */
- if (nan_attr_mask & NAN_ATTR_OUI_CONFIG) {
- ret = wl_cfgnan_set_nan_oui(cmd_data, nan_iov_data);
- if (unlikely(ret)) {
- WL_ERR(("nan_oui sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- }
- /* setting nan awake dws */
- ret = wl_cfgnan_set_awake_dws(ndev, cmd_data,
- nan_iov_data, cfg, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("nan awake dws set failed\n"));
- goto fail;
- } else {
- nan_buf->count++;
- }
- /* enable events */
- ret = wl_cfgnan_config_eventmask(ndev, cfg, cmd_data->disc_ind_cfg, false);
- if (unlikely(ret)) {
- WL_ERR(("Failed to config disc ind flag in event_mask, ret = %d\n", ret));
- goto fail;
- }
- /* setting nan enable sub_cmd */
- ret = wl_cfgnan_enable_handler(nan_iov_data, true);
- if (unlikely(ret)) {
- WL_ERR(("enable handler sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- nan_buf->is_set = true;
- nan_buf_size -= nan_iov_data->nan_iov_len;
- memset(resp_buf, 0, sizeof(resp_buf));
- /* Reset conditon variable */
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size,
- &(cmd_data->status), (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan start handler, enable failed, ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- timeout = wait_event_timeout(cfg->nancfg.nan_event_wait,
- cfg->nancfg.nan_event_recvd, msecs_to_jiffies(NAN_START_STOP_TIMEOUT));
- if (!timeout) {
- WL_ERR(("Timed out while Waiting for WL_NAN_EVENT_START event !!!\n"));
- ret = BCME_ERROR;
- goto fail;
- }
- /* If set, auto datapath confirms will be sent by FW */
- ret = wl_cfgnan_config_control_flag(ndev, cfg, WL_NAN_CTRL_AUTO_DPCONF,
- &(cmd_data->status), true);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan control set config handler, ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- /* By default set NAN proprietary rates */
- ret = wl_cfgnan_config_control_flag(ndev, cfg, WL_NAN_CTRL_PROP_RATE,
- &(cmd_data->status), true);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan proprietary rate set failed, ret = %d status = %d \n",
- ret, cmd_data->status));
- goto fail;
- }
- /* malloc for ndp peer list */
- if ((ret = wl_cfgnan_get_capablities_handler(ndev, cfg, &capabilities))
- == BCME_OK) {
- cfg->nancfg.max_ndp_count = capabilities.max_ndp_sessions;
- cfg->nancfg.nan_ndp_peer_info = MALLOCZ(cfg->osh,
- cfg->nancfg.max_ndp_count * sizeof(nan_ndp_peer_t));
- if (!cfg->nancfg.nan_ndp_peer_info) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- } else {
- WL_ERR(("wl_cfgnan_get_capablities_handler failed, ret = %d\n", ret));
- goto fail;
- }
- cfg->nan_enable = true;
- WL_INFORM_MEM(("[NAN] Enable successfull \n"));
- /* disable TDLS on NAN NMI IF create */
- wl_cfg80211_tdls_config(cfg, TDLS_STATE_NMI_CREATE, false);
- fail:
- /* reset conditon variable */
- cfg->nancfg.nan_event_recvd = false;
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- cfg->nan_enable = false;
- mutex_lock(&cfg->if_sync);
- ret = wl_cfg80211_delete_iface(cfg, WL_IF_TYPE_NAN);
- if (ret != BCME_OK) {
- WL_ERR(("failed to delete NDI[%d]\n", ret));
- }
- mutex_unlock(&cfg->if_sync);
- }
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- if (nan_iov_data) {
- MFREE(cfg->osh, nan_iov_data, sizeof(*nan_iov_data));
- }
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_disable(struct bcm_cfg80211 *cfg, nan_stop_reason_code_t reason)
- {
- s32 ret = BCME_OK;
- dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
- #ifdef RTT_SUPPORT
- rtt_status_info_t *rtt_status = GET_RTTSTATE(dhdp);
- rtt_target_info_t *target_info = NULL;
- #endif /* RTT_SUPPORT */
- NAN_DBG_ENTER();
- if ((cfg->nan_init_state == TRUE) &&
- (cfg->nan_enable == TRUE)) {
- struct net_device *ndev;
- ndev = bcmcfg_to_prmry_ndev(cfg);
- /* We have to remove NDIs so that P2P/Softap can work */
- ret = wl_cfg80211_delete_iface(cfg, WL_IF_TYPE_NAN);
- if (ret != BCME_OK) {
- WL_ERR(("failed to delete NDI[%d]\n", ret));
- }
- WL_INFORM_MEM(("Nan Disable Req, reason = %d\n", reason));
- cfg->nancfg.disable_reason = reason;
- ret = wl_cfgnan_stop_handler(ndev, cfg, false);
- if (ret == -ENODEV) {
- WL_ERR(("Bus is down, no need to proceed\n"));
- } else if (ret != BCME_OK) {
- WL_ERR(("failed to stop nan, error[%d]\n", ret));
- }
- ret = wl_cfgnan_deinit(cfg, dhdp->up);
- if (ret != BCME_OK) {
- WL_ERR(("failed to de-initialize NAN[%d]\n", ret));
- if (!dhd_query_bus_erros(dhdp)) {
- ASSERT(0);
- }
- }
- #ifdef RTT_SUPPORT
- /* Delete the geofence rtt target list */
- dhd_rtt_delete_geofence_target_list(dhdp);
- /* Remove if any pending proxd timeout for nan-rtt */
- target_info = &rtt_status->rtt_config.target_info[rtt_status->cur_idx];
- if (target_info && target_info->peer == RTT_PEER_NAN) {
- /* Cancel pending proxd timeout work if any */
- if (delayed_work_pending(&rtt_status->proxd_timeout)) {
- cancel_delayed_work(&rtt_status->proxd_timeout);
- }
- }
- /* Delete if any directed nan rtt session */
- dhd_rtt_delete_nan_session(dhdp);
- #endif /* RTT_SUPPORT */
- if (cfg->nancfg.nan_ndp_peer_info) {
- MFREE(cfg->osh, cfg->nancfg.nan_ndp_peer_info,
- cfg->nancfg.max_ndp_count * sizeof(nan_ndp_peer_t));
- cfg->nancfg.nan_ndp_peer_info = NULL;
- }
- }
- NAN_DBG_EXIT();
- return ret;
- }
- static void
- wl_cfgnan_send_stop_event(struct bcm_cfg80211 *cfg)
- {
- s32 ret = BCME_OK;
- nan_event_data_t *nan_event_data = NULL;
- NAN_DBG_ENTER();
- if (cfg->nancfg.disable_reason == NAN_USER_INITIATED) {
- /* do not event to host if command is from host */
- goto exit;
- }
- nan_event_data = MALLOCZ(cfg->osh, sizeof(nan_event_data_t));
- if (!nan_event_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto exit;
- }
- bzero(nan_event_data, sizeof(nan_event_data_t));
- if (cfg->nancfg.disable_reason == NAN_CONCURRENCY_CONFLICT) {
- nan_event_data->status = NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
- } else {
- nan_event_data->status = NAN_STATUS_SUCCESS;
- }
- nan_event_data->status = NAN_STATUS_SUCCESS;
- ret = memcpy_s(nan_event_data->nan_reason, NAN_ERROR_STR_LEN,
- "NAN_STATUS_SUCCESS", strlen("NAN_STATUS_SUCCESS"));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nan reason string, ret = %d\n", ret));
- goto exit;
- }
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
- ret = wl_cfgvendor_send_nan_event(cfg->wdev->wiphy, bcmcfg_to_prmry_ndev(cfg),
- GOOGLE_NAN_EVENT_DISABLED, nan_event_data);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to send event to nan hal, (%d)\n",
- GOOGLE_NAN_EVENT_DISABLED));
- }
- #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
- exit:
- if (nan_event_data) {
- MFREE(cfg->osh, nan_event_data, sizeof(nan_event_data_t));
- }
- NAN_DBG_EXIT();
- return;
- }
- int
- wl_cfgnan_stop_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, bool disable_events)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- wl_nan_iov_t *nan_iov_data = NULL;
- uint32 status;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- s32 timeout;
- bool mutex_locked = false;
- dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- mutex_locked = true;
- if (!cfg->nan_enable) {
- WL_INFORM(("Nan is not enabled\n"));
- ret = BCME_OK;
- goto fail;
- }
- if (cfg->nancfg.disable_reason != NAN_BUS_IS_DOWN) {
- /*
- * Framework doing cleanup(iface remove) on disable command,
- * so avoiding event to prevent iface delete calls again
- */
- if (disable_events) {
- WL_INFORM_MEM(("[NAN] Disabling Nan events\n"));
- wl_cfgnan_config_eventmask(ndev, cfg, 0, true);
- }
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data = MALLOCZ(cfg->osh, sizeof(*nan_iov_data));
- if (!nan_iov_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data->nan_iov_len = NAN_IOCTL_BUF_SIZE;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- ret = wl_cfgnan_enable_handler(nan_iov_data, false);
- if (unlikely(ret)) {
- WL_ERR(("nan disable handler failed\n"));
- goto fail;
- }
- nan_buf->count++;
- nan_buf->is_set = true;
- nan_buf_size -= nan_iov_data->nan_iov_len;
- memset_s(resp_buf, sizeof(resp_buf),
- 0, sizeof(resp_buf));
- mutex_locked = false;
- /* reset conditon variable */
- cfg->nancfg.nan_event_recvd = false;
- /* Releasing lock to allow event processing */
- NAN_MUTEX_UNLOCK();
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("nan disable failed ret = %d status = %d\n", ret, status));
- goto fail;
- }
- timeout = wait_event_timeout(cfg->nancfg.nan_event_wait,
- cfg->nancfg.nan_event_recvd,
- msecs_to_jiffies(NAN_START_STOP_TIMEOUT));
- if (!timeout) {
- WL_ERR(("Timed out while Waiting for WL_NAN_EVENT_STOP event !!!\n"));
- if (!dhd_query_bus_erros(dhdp)) {
- ASSERT(0);
- }
- ret = BCME_ERROR;
- goto fail;
- }
- WL_INFORM_MEM(("[NAN] Disable done\n"));
- /* Enable back TDLS if connected interface is <= 1 */
- wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_DELETE, false);
- }
- wl_cfgnan_send_stop_event(cfg);
- fail:
- /* Resetting instance ID mask */
- cfg->nancfg.inst_id_start = 0;
- memset(cfg->nancfg.svc_inst_id_mask, 0, sizeof(cfg->nancfg.svc_inst_id_mask));
- memset(cfg->svc_info, 0, NAN_MAX_SVC_INST * sizeof(nan_svc_info_t));
- /* reset conditon variable */
- cfg->nancfg.nan_event_recvd = false;
- cfg->nan_enable = false;
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- if (nan_iov_data) {
- MFREE(cfg->osh, nan_iov_data, sizeof(*nan_iov_data));
- }
- if (mutex_locked)
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_config_handler(struct net_device *ndev, struct bcm_cfg80211 *cfg,
- nan_config_cmd_data_t *cmd_data, uint32 nan_attr_mask)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- wl_nan_iov_t *nan_iov_data = NULL;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- NAN_DBG_ENTER();
- /* Nan need to be enabled before configuring/updating params */
- if (cfg->nan_enable) {
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data = MALLOCZ(cfg->osh, sizeof(*nan_iov_data));
- if (!nan_iov_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data->nan_iov_len = NAN_IOCTL_BUF_SIZE;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- /* setting sid beacon val */
- if ((nan_attr_mask & NAN_ATTR_SID_BEACON_CONFIG) ||
- (nan_attr_mask & NAN_ATTR_SUB_SID_BEACON_CONFIG)) {
- ret = wl_cfgnan_set_sid_beacon_val(cmd_data, nan_iov_data, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("sid_beacon sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- }
- /* setting master preference and random factor */
- if (cmd_data->metrics.random_factor ||
- cmd_data->metrics.master_pref) {
- ret = wl_cfgnan_set_election_metric(cmd_data, nan_iov_data,
- nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("election_metric sub_cmd set failed\n"));
- goto fail;
- } else {
- nan_buf->count++;
- }
- }
- /* setting hop count limit or threshold */
- if (nan_attr_mask & NAN_ATTR_HOP_COUNT_LIMIT_CONFIG) {
- ret = wl_cfgnan_set_hop_count_limit(cmd_data, nan_iov_data);
- if (unlikely(ret)) {
- WL_ERR(("hop_count_limit sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- }
- /* setting rssi proximaty values for 2.4GHz and 5GHz */
- ret = wl_cfgnan_set_rssi_proximity(cmd_data, nan_iov_data,
- nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("2.4GHz/5GHz rssi proximity threshold set failed\n"));
- goto fail;
- } else {
- nan_buf->count++;
- }
- /* setting nan awake dws */
- ret = wl_cfgnan_set_awake_dws(ndev, cmd_data, nan_iov_data,
- cfg, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("nan awake dws set failed\n"));
- goto fail;
- } else {
- nan_buf->count++;
- }
- if (cmd_data->disc_ind_cfg) {
- /* Disable events */
- WL_TRACE(("Disable events based on flag\n"));
- ret = wl_cfgnan_config_eventmask(ndev, cfg,
- cmd_data->disc_ind_cfg, false);
- if (unlikely(ret)) {
- WL_ERR(("Failed to config disc ind flag in event_mask, ret = %d\n",
- ret));
- goto fail;
- }
- }
- if ((cfg->support_5g) && ((cmd_data->dwell_time[1]) ||
- (cmd_data->scan_period[1]))) {
- /* setting scan params */
- ret = wl_cfgnan_set_nan_scan_params(ndev, cfg,
- cmd_data, cfg->support_5g, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("scan params set failed for 5g\n"));
- goto fail;
- }
- }
- if ((cmd_data->dwell_time[0]) ||
- (cmd_data->scan_period[0])) {
- ret = wl_cfgnan_set_nan_scan_params(ndev, cfg, cmd_data, 0, nan_attr_mask);
- if (unlikely(ret)) {
- WL_ERR(("scan params set failed for 2g\n"));
- goto fail;
- }
- }
- nan_buf->is_set = true;
- nan_buf_size -= nan_iov_data->nan_iov_len;
- if (nan_buf->count) {
- memset_s(resp_buf, sizeof(resp_buf),
- 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size,
- &(cmd_data->status),
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR((" nan config handler failed ret = %d status = %d\n",
- ret, cmd_data->status));
- goto fail;
- }
- } else {
- WL_DBG(("No commands to send\n"));
- }
- if ((!cmd_data->bmap) || (cmd_data->avail_params.duration == NAN_BAND_INVALID) ||
- (!cmd_data->chanspec[0])) {
- WL_TRACE(("mandatory arguments are not present to set avail\n"));
- ret = BCME_OK;
- } else {
- cmd_data->avail_params.chanspec[0] = cmd_data->chanspec[0];
- cmd_data->avail_params.bmap = cmd_data->bmap;
- /* 1=local, 2=peer, 3=ndc, 4=immutable, 5=response, 6=counter */
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data->avail_params, WL_AVAIL_LOCAL);
- if (unlikely(ret)) {
- WL_ERR(("Failed to set avail value with type local\n"));
- goto fail;
- }
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data->avail_params, WL_AVAIL_NDC);
- if (unlikely(ret)) {
- WL_ERR(("Failed to set avail value with type ndc\n"));
- goto fail;
- }
- }
- } else {
- WL_INFORM(("nan is not enabled\n"));
- }
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- if (nan_iov_data) {
- MFREE(cfg->osh, nan_iov_data, sizeof(*nan_iov_data));
- }
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_support_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_config_cmd_data_t *cmd_data)
- {
- /* TODO: */
- return BCME_OK;
- }
- int
- wl_cfgnan_status_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_config_cmd_data_t *cmd_data)
- {
- /* TODO: */
- return BCME_OK;
- }
- #ifdef WL_NAN_DISC_CACHE
- static
- nan_svc_info_t *
- wl_cfgnan_get_svc_inst(struct bcm_cfg80211 *cfg,
- wl_nan_instance_id svc_inst_id, uint8 ndp_id)
- {
- uint8 i, j;
- if (ndp_id) {
- for (i = 0; i < NAN_MAX_SVC_INST; i++) {
- for (j = 0; j < NAN_MAX_SVC_INST; j++) {
- if (cfg->svc_info[i].ndp_id[j] == ndp_id) {
- return &cfg->svc_info[i];
- }
- }
- }
- } else if (svc_inst_id) {
- for (i = 0; i < NAN_MAX_SVC_INST; i++) {
- if (cfg->svc_info[i].svc_id == svc_inst_id) {
- return &cfg->svc_info[i];
- }
- }
- }
- return NULL;
- }
- nan_ranging_inst_t *
- wl_cfgnan_check_for_ranging(struct bcm_cfg80211 *cfg, struct ether_addr *peer)
- {
- uint8 i;
- if (peer) {
- for (i = 0; i < NAN_MAX_RANGING_INST; i++) {
- if (!memcmp(peer, &cfg->nan_ranging_info[i].peer_addr,
- ETHER_ADDR_LEN)) {
- return &(cfg->nan_ranging_info[i]);
- }
- }
- }
- return NULL;
- }
- /*
- * Find ranging inst for given peer,
- * On not found, create one
- * with given range role
- */
- nan_ranging_inst_t *
- wl_cfgnan_get_ranging_inst(struct bcm_cfg80211 *cfg, struct ether_addr *peer,
- nan_range_role_t range_role)
- {
- nan_ranging_inst_t *ranging_inst = NULL;
- uint8 i;
- ranging_inst = wl_cfgnan_check_for_ranging(cfg, peer);
- if (ranging_inst) {
- goto done;
- }
- WL_TRACE(("Creating Ranging instance \n"));
- for (i = 0; i < NAN_MAX_RANGING_INST; i++) {
- if (cfg->nan_ranging_info[i].in_use == FALSE) {
- break;
- }
- }
- if (i == NAN_MAX_RANGING_INST) {
- WL_ERR(("No buffer available for the ranging instance"));
- goto done;
- }
- ranging_inst = &cfg->nan_ranging_info[i];
- memcpy(&ranging_inst->peer_addr, peer, ETHER_ADDR_LEN);
- ranging_inst->range_status = NAN_RANGING_REQUIRED;
- ranging_inst->prev_distance_mm = INVALID_DISTANCE;
- ranging_inst->range_role = range_role;
- ranging_inst->in_use = TRUE;
- done:
- return ranging_inst;
- }
- #endif /* WL_NAN_DISC_CACHE */
- static int
- process_resp_buf(void *iov_resp,
- uint8 *instance_id, uint16 sub_cmd_id)
- {
- int res = BCME_OK;
- NAN_DBG_ENTER();
- if (sub_cmd_id == WL_NAN_CMD_DATA_DATAREQ) {
- wl_nan_dp_req_ret_t *dpreq_ret = NULL;
- dpreq_ret = (wl_nan_dp_req_ret_t *)(iov_resp);
- *instance_id = dpreq_ret->ndp_id;
- WL_TRACE(("%s: Initiator NDI: " MACDBG "\n",
- __FUNCTION__, MAC2STRDBG(dpreq_ret->indi.octet)));
- } else if (sub_cmd_id == WL_NAN_CMD_RANGE_REQUEST) {
- wl_nan_range_id *range_id = NULL;
- range_id = (wl_nan_range_id *)(iov_resp);
- *instance_id = *range_id;
- WL_TRACE(("Range id: %d\n", *range_id));
- }
- WL_DBG(("instance_id: %d\n", *instance_id));
- NAN_DBG_EXIT();
- return res;
- }
- int
- wl_cfgnan_cancel_ranging(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, uint8 range_id, uint8 flags, uint32 *status)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_iov_start, nan_iov_end;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint16 subcmd_len;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- wl_nan_iov_t *nan_iov_data = NULL;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- wl_nan_range_cancel_ext_t rng_cncl;
- uint8 size_of_iov;
- NAN_DBG_ENTER();
- if (cfg->nancfg.version >= NAN_RANGE_EXT_CANCEL_SUPPORT_VER) {
- size_of_iov = sizeof(rng_cncl);
- } else {
- size_of_iov = sizeof(range_id);
- }
- memset_s(&rng_cncl, sizeof(rng_cncl), 0, sizeof(rng_cncl));
- rng_cncl.range_id = range_id;
- rng_cncl.flags = flags;
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data = MALLOCZ(cfg->osh, sizeof(*nan_iov_data));
- if (!nan_iov_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_iov_data->nan_iov_len = nan_iov_start = NAN_IOCTL_BUF_SIZE;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_iov_data->nan_iov_buf = (uint8 *)(&nan_buf->cmds[0]);
- nan_iov_data->nan_iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(nan_iov_data->nan_iov_buf);
- ret = wl_cfg_nan_check_cmd_len(nan_iov_data->nan_iov_len,
- size_of_iov, &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- sub_cmd->id = htod16(WL_NAN_CMD_RANGE_CANCEL);
- sub_cmd->len = sizeof(sub_cmd->u.options) + size_of_iov;
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- /* Reduce the iov_len size by subcmd_len */
- nan_iov_data->nan_iov_len -= subcmd_len;
- nan_iov_end = nan_iov_data->nan_iov_len;
- nan_buf_size = (nan_iov_start - nan_iov_end);
- if (size_of_iov >= sizeof(rng_cncl)) {
- (void)memcpy_s(sub_cmd->data, nan_iov_data->nan_iov_len,
- &rng_cncl, size_of_iov);
- } else {
- (void)memcpy_s(sub_cmd->data, nan_iov_data->nan_iov_len,
- &range_id, size_of_iov);
- }
- nan_buf->is_set = true;
- nan_buf->count++;
- memset_s(resp_buf, sizeof(resp_buf),
- 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(*status)) {
- WL_ERR(("Range ID %d cancel failed ret %d status %d \n", range_id, ret, *status));
- goto fail;
- }
- WL_MEM(("Range cancel with Range ID [%d] successfull\n", range_id));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- if (nan_iov_data) {
- MFREE(cfg->osh, nan_iov_data, sizeof(*nan_iov_data));
- }
- NAN_DBG_EXIT();
- return ret;
- }
- #ifdef WL_NAN_DISC_CACHE
- static int
- wl_cfgnan_cache_svc_info(struct bcm_cfg80211 *cfg,
- nan_discover_cmd_data_t *cmd_data, uint16 cmd_id, bool update)
- {
- int ret = BCME_OK;
- int i;
- nan_svc_info_t *svc_info;
- uint8 svc_id = (cmd_id == WL_NAN_CMD_SD_SUBSCRIBE) ? cmd_data->sub_id :
- cmd_data->pub_id;
- for (i = 0; i < NAN_MAX_SVC_INST; i++) {
- if (update) {
- if (cfg->svc_info[i].svc_id == svc_id) {
- svc_info = &cfg->svc_info[i];
- break;
- } else {
- continue;
- }
- }
- if (!cfg->svc_info[i].svc_id) {
- svc_info = &cfg->svc_info[i];
- break;
- }
- }
- if (i == NAN_MAX_SVC_INST) {
- WL_ERR(("%s:cannot accomodate ranging session\n", __FUNCTION__));
- ret = BCME_NORESOURCE;
- goto fail;
- }
- if (cmd_data->sde_control_flag & NAN_SDE_CF_RANGING_REQUIRED) {
- WL_TRACE(("%s: updating ranging info, enabling", __FUNCTION__));
- svc_info->status = 1;
- svc_info->ranging_interval = cmd_data->ranging_intvl_msec;
- svc_info->ranging_ind = cmd_data->ranging_indication;
- svc_info->ingress_limit = cmd_data->ingress_limit;
- svc_info->egress_limit = cmd_data->egress_limit;
- svc_info->ranging_required = 1;
- } else {
- WL_TRACE(("%s: updating ranging info, disabling", __FUNCTION__));
- svc_info->status = 0;
- svc_info->ranging_interval = 0;
- svc_info->ranging_ind = 0;
- svc_info->ingress_limit = 0;
- svc_info->egress_limit = 0;
- svc_info->ranging_required = 0;
- }
- /* Reset Range status flags on svc creation/update */
- svc_info->svc_range_status = 0;
- svc_info->flags = cmd_data->flags;
- if (cmd_id == WL_NAN_CMD_SD_SUBSCRIBE) {
- svc_info->svc_id = cmd_data->sub_id;
- if ((cmd_data->flags & WL_NAN_SUB_ACTIVE) &&
- (cmd_data->tx_match.dlen)) {
- ret = memcpy_s(svc_info->tx_match_filter, sizeof(svc_info->tx_match_filter),
- cmd_data->tx_match.data, cmd_data->tx_match.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy tx match filter data\n"));
- goto fail;
- }
- svc_info->tx_match_filter_len = cmd_data->tx_match.dlen;
- }
- } else {
- svc_info->svc_id = cmd_data->pub_id;
- }
- ret = memcpy_s(svc_info->svc_hash, sizeof(svc_info->svc_hash),
- cmd_data->svc_hash.data, WL_NAN_SVC_HASH_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy svc hash\n"));
- }
- fail:
- return ret;
- }
- static int
- wl_cfgnan_clear_svc_ranging_inst(struct bcm_cfg80211 *cfg, uint8 svc_id)
- {
- nan_ranging_inst_t *ranging_inst;
- int i = 0, j;
- int ret = BCME_OK;
- nan_svc_info_t *svc = wl_cfgnan_get_svc_inst(cfg, svc_id, 0);
- if (!svc) {
- WL_ERR(("\n svc not found \n"));
- ret = BCME_NOTFOUND;
- goto done;
- }
- for (i = 0; i < NAN_MAX_RANGING_INST; i++) {
- ranging_inst = &(cfg->nan_ranging_info[i]);
- if (ranging_inst->range_id) {
- for (j = 0; j < MAX_SUBSCRIBES; j++) {
- if (svc == ranging_inst->svc_idx[j]) {
- ranging_inst->num_svc_ctx--;
- ranging_inst->svc_idx[j] = NULL;
- }
- }
- }
- }
- done:
- return ret;
- }
- #ifdef RTT_SUPPORT
- /* API to terminate/clear all directed nan-rtt sessions.
- * Can be called from framework RTT stop context
- */
- int
- wl_cfgnan_terminate_directed_rtt_sessions(struct net_device *ndev,
- struct bcm_cfg80211 *cfg)
- {
- nan_ranging_inst_t *ranging_inst;
- int i, ret = BCME_OK;
- uint32 status;
- for (i = 0; i < NAN_MAX_RANGING_INST; i++) {
- ranging_inst = &cfg->nan_ranging_info[i];
- if (ranging_inst->range_id && ranging_inst->range_type == RTT_TYPE_NAN_DIRECTED) {
- if (ranging_inst->range_status == NAN_RANGING_IN_PROGRESS) {
- ret = wl_cfgnan_cancel_ranging(ndev, cfg, ranging_inst->range_id,
- NAN_RNG_TERM_FLAG_IMMEDIATE, &status);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("nan range cancel failed ret = %d status = %d\n",
- ret, status));
- }
- }
- wl_cfgnan_reset_geofence_ranging(cfg, ranging_inst,
- RTT_SHCED_HOST_DIRECTED_TERM);
- }
- }
- return ret;
- }
- #endif /* RTT_SUPPORT */
- /*
- * suspend ongoing geofence ranging session
- * with a peer if on-going ranging is with given peer
- * If peer NULL,
- * Suspend on-going ranging blindly
- * Do nothing on:
- * If ranging is not in progress
- * If ranging in progress but not with given peer
- */
- int
- wl_cfgnan_suspend_geofence_rng_session(struct net_device *ndev,
- struct ether_addr *peer, int suspend_reason, u8 cancel_flags)
- {
- int ret = BCME_OK;
- uint32 status;
- nan_ranging_inst_t *ranging_inst = NULL;
- struct ether_addr* peer_addr = NULL;
- struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
- #ifdef RTT_SUPPORT
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- rtt_geofence_target_info_t *geofence_target_info;
- geofence_target_info = dhd_rtt_get_geofence_current_target(dhd);
- if (!geofence_target_info) {
- goto exit;
- }
- peer_addr = &geofence_target_info->peer_addr;
- ranging_inst = wl_cfgnan_check_for_ranging(cfg, peer_addr);
- if (dhd_rtt_get_geofence_rtt_state(dhd) == FALSE) {
- WL_DBG(("Geofencing Ranging not in progress, suspend req dropped\n"));
- goto exit;
- }
- if (peer && memcmp(peer_addr, peer, ETHER_ADDR_LEN)) {
- if (suspend_reason == RTT_GEO_SUSPN_HOST_NDP_TRIGGER ||
- suspend_reason == RTT_GEO_SUSPN_PEER_NDP_TRIGGER) {
- /* NDP and Ranging can coexist with different Peers */
- WL_DBG(("Geofencing Ranging not in progress with given peer,"
- " suspend req dropped\n"));
- goto exit;
- }
- }
- #endif /* RTT_SUPPORT */
- ASSERT((ranging_inst != NULL));
- if (ranging_inst) {
- if (ranging_inst->range_status != NAN_RANGING_IN_PROGRESS) {
- goto exit;
- }
- cancel_flags |= NAN_RNG_TERM_FLAG_IMMEDIATE;
- ret = wl_cfgnan_cancel_ranging(ndev, cfg,
- ranging_inst->range_id, cancel_flags, &status);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("Geofence Range suspended failed, err = %d, status = %d,"
- " range_id = %d, suspend_reason = %d, " MACDBG " \n",
- ret, status, ranging_inst->range_id,
- suspend_reason, MAC2STRDBG(peer_addr)));
- }
- ranging_inst->range_status = NAN_RANGING_REQUIRED;
- WL_INFORM_MEM(("Geofence Range suspended, range_id = %d,"
- " cancel_reason = %d, " MACDBG " \n", ranging_inst->range_id,
- suspend_reason, MAC2STRDBG(peer_addr)));
- #ifdef RTT_SUPPORT
- /* Set geofence RTT in progress state to false */
- dhd_rtt_set_geofence_rtt_state(dhd, FALSE);
- #endif /* RTT_SUPPORT */
- }
- exit:
- /* Post pending discovery results */
- if (ranging_inst &&
- ((suspend_reason == RTT_GEO_SUSPN_HOST_NDP_TRIGGER) ||
- (suspend_reason == RTT_GEO_SUSPN_PEER_NDP_TRIGGER))) {
- wl_cfgnan_disc_result_on_geofence_cancel(cfg, ranging_inst);
- }
- return ret;
- }
- static void
- wl_cfgnan_clear_svc_cache(struct bcm_cfg80211 *cfg,
- wl_nan_instance_id svc_id)
- {
- nan_svc_info_t *svc;
- svc = wl_cfgnan_get_svc_inst(cfg, svc_id, 0);
- if (svc) {
- WL_DBG(("clearing cached svc info for svc id %d\n", svc_id));
- memset(svc, 0, sizeof(*svc));
- }
- }
- static int
- wl_cfgnan_terminate_ranging_sessions(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, uint8 svc_id)
- {
- /* cancel all related ranging instances */
- uint8 i;
- int ret = BCME_OK;
- uint32 status;
- nan_ranging_inst_t *ranging_inst;
- #ifdef RTT_SUPPORT
- int8 index = -1;
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- rtt_geofence_target_info_t* geofence_target;
- #endif /* RTT_SUPPORT */
- for (i = 0; i < NAN_MAX_RANGING_INST; i++) {
- ranging_inst = &cfg->nan_ranging_info[i];
- if (ranging_inst->num_svc_ctx == 0 &&
- ranging_inst->range_role == NAN_RANGING_ROLE_INITIATOR) {
- if (ranging_inst->range_id) {
- ret = wl_cfgnan_cancel_ranging(ndev, cfg, ranging_inst->range_id,
- NAN_RNG_TERM_FLAG_NONE, &status);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("%s:nan range cancel failed ret = %d status = %d\n",
- __FUNCTION__, ret, status));
- goto exit;
- }
- WL_DBG(("Range cancelled \n"));
- }
- #ifdef RTT_SUPPORT
- /* Set geofence RTT in progress state to false */
- geofence_target = dhd_rtt_get_geofence_target(dhd,
- &ranging_inst->peer_addr, &index);
- if (geofence_target) {
- dhd_rtt_remove_geofence_target(dhd, &geofence_target->peer_addr);
- }
- WL_INFORM_MEM(("Removing Ranging Instance " MACDBG "\n",
- MAC2STRDBG(&(ranging_inst->peer_addr))));
- bzero(ranging_inst, sizeof(nan_ranging_inst_t));
- if (index == 0) {
- /* If the target was the geofence queue head */
- dhd_rtt_set_geofence_rtt_state(dhd, FALSE);
- }
- #endif /* RTT_SUPPORT */
- }
- }
- exit:
- return ret;
- }
- /*
- * Store svc_ctx for processing during RNG_RPT
- * Return BCME_OK only when svc is added
- */
- static int
- wl_cfgnan_update_ranging_svc_inst(nan_ranging_inst_t *ranging_inst,
- nan_svc_info_t *svc)
- {
- int ret = BCME_OK;
- int i = 0;
- for (i = 0; i < MAX_SUBSCRIBES; i++) {
- if (ranging_inst->svc_idx[i] == svc) {
- WL_DBG(("SVC Ctx for ranging already present, "
- " Duplication not supported: sub_id: %d\n", svc->svc_id));
- ret = BCME_UNSUPPORTED;
- goto done;
- }
- }
- for (i = 0; i < MAX_SUBSCRIBES; i++) {
- if (ranging_inst->svc_idx[i]) {
- continue;
- } else {
- WL_DBG(("Adding SVC Ctx for ranging..svc_id %d\n", svc->svc_id));
- ranging_inst->svc_idx[i] = svc;
- ranging_inst->num_svc_ctx++;
- ret = BCME_OK;
- goto done;
- }
- }
- if (i == MAX_SUBSCRIBES) {
- WL_ERR(("wl_cfgnan_update_ranging_svc_inst: "
- "No resource to hold Ref SVC ctx..svc_id %d\n", svc->svc_id));
- ret = BCME_NORESOURCE;
- goto done;
- }
- done:
- return ret;
- }
- #ifdef RTT_SUPPORT
- int
- wl_cfgnan_trigger_geofencing_ranging(struct net_device *dev,
- struct ether_addr *peer_addr)
- {
- int ret = BCME_OK;
- int err_at = 0;
- struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
- int8 index = -1;
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- rtt_geofence_target_info_t* geofence_target;
- nan_ranging_inst_t *ranging_inst;
- ranging_inst = wl_cfgnan_check_for_ranging(cfg, peer_addr);
- if (!ranging_inst) {
- WL_INFORM_MEM(("Ranging Entry for peer:" MACDBG ", not found\n",
- MAC2STRDBG(peer_addr)));
- ASSERT(0);
- /* Ranging inst should have been added before adding target */
- dhd_rtt_remove_geofence_target(dhd, peer_addr);
- ret = BCME_ERROR;
- err_at = 1;
- goto exit;
- }
- ASSERT(ranging_inst->range_status !=
- NAN_RANGING_IN_PROGRESS);
- if (ranging_inst->range_status !=
- NAN_RANGING_IN_PROGRESS) {
- WL_DBG(("Trigger range request with first svc in svc list of range inst\n"));
- ret = wl_cfgnan_trigger_ranging(bcmcfg_to_prmry_ndev(cfg),
- cfg, ranging_inst, ranging_inst->svc_idx[0],
- NAN_RANGE_REQ_CMD, TRUE);
- if (ret != BCME_OK) {
- /* Unsupported is for already ranging session for peer */
- if (ret == BCME_BUSY) {
- /* TODO: Attempt again over a timer */
- err_at = 2;
- } else {
- /* Remove target and clean ranging inst */
- geofence_target = dhd_rtt_get_geofence_target(dhd,
- &ranging_inst->peer_addr, &index);
- if (geofence_target) {
- dhd_rtt_remove_geofence_target(dhd,
- &geofence_target->peer_addr);
- }
- bzero(ranging_inst, sizeof(nan_ranging_inst_t));
- err_at = 3;
- goto exit;
- }
- }
- } else {
- /* already in progress..This should not happen */
- ASSERT(0);
- ret = BCME_ERROR;
- err_at = 4;
- goto exit;
- }
- exit:
- if (ret) {
- WL_ERR(("wl_cfgnan_trigger_geofencing_ranging: Failed to "
- "trigger ranging, peer: " MACDBG " ret"
- " = (%d), err_at = %d\n", MAC2STRDBG(peer_addr),
- ret, err_at));
- }
- return ret;
- }
- #endif /* RTT_SUPPORT */
- static int
- wl_cfgnan_check_disc_result_for_ranging(struct bcm_cfg80211 *cfg,
- nan_event_data_t* nan_event_data)
- {
- nan_svc_info_t *svc;
- int ret = BCME_OK;
- #ifdef RTT_SUPPORT
- rtt_geofence_target_info_t geofence_target;
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- uint8 index;
- #endif /* RTT_SUPPORT */
- bool add_target;
- svc = wl_cfgnan_get_svc_inst(cfg, nan_event_data->sub_id, 0);
- if (svc && svc->ranging_required) {
- nan_ranging_inst_t *ranging_inst;
- ranging_inst = wl_cfgnan_get_ranging_inst(cfg,
- &nan_event_data->remote_nmi,
- NAN_RANGING_ROLE_INITIATOR);
- if (!ranging_inst) {
- ret = BCME_NORESOURCE;
- goto exit;
- }
- ASSERT(ranging_inst->range_role != NAN_RANGING_ROLE_INVALID);
- /* For responder role, range state should be in progress only */
- ASSERT(ranging_inst->range_role == NAN_RANGING_ROLE_INITIATOR ||
- ranging_inst->range_status == NAN_RANGING_IN_PROGRESS);
- /*
- * On rec disc result with ranging required, add target, if
- * ranging role is responder (range state has to be in prog always)
- * Or ranging role is initiator and ranging is not already in prog
- */
- add_target = ((ranging_inst->range_role == NAN_RANGING_ROLE_RESPONDER) ||
- ((ranging_inst->range_role == NAN_RANGING_ROLE_INITIATOR) &&
- (ranging_inst->range_status != NAN_RANGING_IN_PROGRESS)));
- if (add_target) {
- WL_DBG(("Add Range request to geofence target list\n"));
- #ifdef RTT_SUPPORT
- memcpy(&geofence_target.peer_addr, &nan_event_data->remote_nmi,
- ETHER_ADDR_LEN);
- /* check if target is already added */
- if (!dhd_rtt_get_geofence_target(dhd, &nan_event_data->remote_nmi, &index))
- {
- ret = dhd_rtt_add_geofence_target(dhd, &geofence_target);
- if (unlikely(ret)) {
- WL_ERR(("Failed to add geofence Tgt, ret = (%d)\n", ret));
- bzero(ranging_inst, sizeof(*ranging_inst));
- goto exit;
- } else {
- WL_INFORM_MEM(("Geofence Tgt Added:" MACDBG " sub_id:%d\n",
- MAC2STRDBG(&geofence_target.peer_addr),
- svc->svc_id));
- }
- ranging_inst->range_type = RTT_TYPE_NAN_GEOFENCE;
- }
- #endif /* RTT_SUPPORT */
- if (wl_cfgnan_update_ranging_svc_inst(ranging_inst, svc)
- != BCME_OK) {
- goto exit;
- }
- #ifdef RTT_SUPPORT
- if (ranging_inst->range_role == NAN_RANGING_ROLE_RESPONDER) {
- /* Adding RTT target while responder, leads to role concurrency */
- dhd_rtt_set_role_concurrency_state(dhd, TRUE);
- }
- else {
- /* Trigger/Reset geofence RTT */
- wl_cfgnan_reset_geofence_ranging(cfg, ranging_inst,
- RTT_SCHED_SUB_MATCH);
- }
- #endif /* RTT_SUPPORT */
- } else {
- /* Target already added, check & add svc_inst ref to rang_inst */
- wl_cfgnan_update_ranging_svc_inst(ranging_inst, svc);
- }
- /* Disc event will be given on receving range_rpt event */
- WL_TRACE(("Disc event will given when Range RPT event is recvd"));
- } else {
- ret = BCME_UNSUPPORTED;
- }
- exit:
- return ret;
- }
- bool
- wl_cfgnan_ranging_allowed(struct bcm_cfg80211 *cfg)
- {
- int i = 0;
- uint8 rng_progress_count = 0;
- nan_ranging_inst_t *ranging_inst = NULL;
- for (i = 0; i < NAN_MAX_RANGING_INST; i++) {
- ranging_inst = &cfg->nan_ranging_info[i];
- if (ranging_inst->range_status == NAN_RANGING_IN_PROGRESS) {
- rng_progress_count++;
- }
- }
- if (rng_progress_count == NAN_MAX_RANGING_SSN_ALLOWED) {
- return FALSE;
- }
- return TRUE;
- }
- uint8
- wl_cfgnan_cancel_rng_responders(struct net_device *ndev,
- struct bcm_cfg80211 *cfg)
- {
- int i = 0;
- uint8 num_resp_cancelled = 0;
- int status, ret;
- nan_ranging_inst_t *ranging_inst = NULL;
- for (i = 0; i < NAN_MAX_RANGING_INST; i++) {
- ranging_inst = &cfg->nan_ranging_info[i];
- if (ranging_inst->range_status == NAN_RANGING_IN_PROGRESS &&
- ranging_inst->range_role == NAN_RANGING_ROLE_RESPONDER) {
- num_resp_cancelled++;
- WL_ERR((" Cancelling responder\n"));
- ret = wl_cfgnan_cancel_ranging(bcmcfg_to_prmry_ndev(cfg), cfg,
- ranging_inst->range_id, NAN_RNG_TERM_FLAG_IMMEDIATE, &status);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("wl_cfgnan_cancel_rng_responders: Failed to cancel"
- " existing ranging, ret = (%d)\n", ret));
- }
- WL_INFORM_MEM(("Removing Ranging Instance " MACDBG "\n",
- MAC2STRDBG(&(ranging_inst->peer_addr))));
- bzero(ranging_inst, sizeof(*ranging_inst));
- }
- }
- return num_resp_cancelled;
- }
- #ifdef RTT_SUPPORT
- /* ranging reqeust event handler */
- static int
- wl_cfgnan_handle_ranging_ind(struct bcm_cfg80211 *cfg,
- wl_nan_ev_rng_req_ind_t *rng_ind)
- {
- int ret = BCME_OK;
- nan_ranging_inst_t *ranging_inst = NULL;
- uint32 status;
- uint8 cancel_flags = 0;
- bool accept = TRUE;
- nan_ranging_inst_t tmp_rng_inst;
- struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
- WL_DBG(("Trigger range response\n"));
- /* check if we are already having any ranging session with peer.
- * If so below are the policies
- * If we are already a Geofence Initiator or responder w.r.t the peer
- * then silently teardown the current session and accept the REQ.
- * If we are in direct rtt initiator role then reject.
- */
- ranging_inst = wl_cfgnan_check_for_ranging(cfg, &(rng_ind->peer_m_addr));
- if (ranging_inst) {
- if (ranging_inst->range_type == RTT_TYPE_NAN_GEOFENCE ||
- ranging_inst->range_role == NAN_RANGING_ROLE_RESPONDER) {
- WL_INFORM_MEM(("Already responder for the Peer, cancel current ssn"
- " and accept new one\n"));
- cancel_flags = NAN_RNG_TERM_FLAG_IMMEDIATE |
- NAN_RNG_TERM_FLAG_SILIENT_TEARDOWN;
- if (ranging_inst->range_type == RTT_TYPE_NAN_GEOFENCE) {
- wl_cfgnan_suspend_geofence_rng_session(ndev,
- &(rng_ind->peer_m_addr), RTT_GEO_SUSPN_PEER_RTT_TRIGGER,
- cancel_flags);
- } else {
- ret = wl_cfgnan_cancel_ranging(ndev, cfg,
- ranging_inst->range_id, cancel_flags, &status);
- if (unlikely(ret)) {
- WL_ERR(("wl_cfgnan_handle_ranging_ind: Failed to cancel"
- " existing ranging, ret = (%d)\n", ret));
- goto done;
- }
- }
- ranging_inst->range_status = NAN_RANGING_REQUIRED;
- ranging_inst->range_role = NAN_RANGING_ROLE_RESPONDER;
- ranging_inst->range_type = 0;
- } else {
- WL_ERR(("Reject the RNG_REQ_IND in direct rtt initiator role\n"));
- ret = BCME_BUSY;
- goto done;
- }
- } else {
- /* Check if new Ranging session is allowed */
- if (!wl_cfgnan_ranging_allowed(cfg)) {
- WL_ERR(("Cannot allow more ranging sessions \n"));
- ret = BCME_NORESOURCE;
- goto done;
- }
- ranging_inst = wl_cfgnan_get_ranging_inst(cfg, &rng_ind->peer_m_addr,
- NAN_RANGING_ROLE_RESPONDER);
- if (!ranging_inst) {
- WL_ERR(("Failed to create ranging instance \n"));
- ASSERT(0);
- ret = BCME_NORESOURCE;
- goto done;
- }
- }
- done:
- if (ret != BCME_OK) {
- /* reject the REQ using temp ranging instance */
- bzero(&tmp_rng_inst, sizeof(tmp_rng_inst));
- ranging_inst = &tmp_rng_inst;
- (void)memcpy_s(&tmp_rng_inst.peer_addr, ETHER_ADDR_LEN,
- &rng_ind->peer_m_addr, ETHER_ADDR_LEN);
- accept = FALSE;
- }
- ranging_inst->range_id = rng_ind->rng_id;
- ret = wl_cfgnan_trigger_ranging(ndev, cfg, ranging_inst,
- NULL, NAN_RANGE_REQ_EVNT, accept);
- if (unlikely(ret) || !accept) {
- WL_ERR(("Failed to handle range request, ret = (%d) accept %d\n",
- ret, accept));
- bzero(ranging_inst, sizeof(*ranging_inst));
- }
- return ret;
- }
- #endif /* RTT_SUPPORT */
- /* ranging quest and response iovar handler */
- int
- wl_cfgnan_trigger_ranging(struct net_device *ndev, struct bcm_cfg80211 *cfg,
- void *ranging_ctxt, nan_svc_info_t *svc,
- uint8 range_cmd, bool accept_req)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_buf_t *nan_buf = NULL;
- wl_nan_range_req_t *range_req = NULL;
- wl_nan_range_resp_t *range_resp = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint32 status;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE_MED];
- nan_ranging_inst_t *ranging_inst = (nan_ranging_inst_t *)ranging_ctxt;
- nan_avail_cmd_data cmd_data;
- NAN_DBG_ENTER();
- memset_s(&cmd_data, sizeof(cmd_data),
- 0, sizeof(cmd_data));
- ret = memcpy_s(&cmd_data.peer_nmi, ETHER_ADDR_LEN,
- &ranging_inst->peer_addr, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy ranging peer addr\n"));
- goto fail;
- }
- cmd_data.avail_period = NAN_RANGING_PERIOD;
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data, WL_AVAIL_LOCAL);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to set avail value with type [WL_AVAIL_LOCAL]\n"));
- goto fail;
- }
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data, WL_AVAIL_RANGING);
- if (unlikely(ret)) {
- WL_ERR(("Failed to set avail value with type [WL_AVAIL_RANGING]\n"));
- goto fail;
- }
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(&nan_buf->cmds[0]);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- if (range_cmd == NAN_RANGE_REQ_CMD) {
- sub_cmd->id = htod16(WL_NAN_CMD_RANGE_REQUEST);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(wl_nan_range_req_t);
- range_req = (wl_nan_range_req_t *)(sub_cmd->data);
- /* ranging config */
- range_req->peer = ranging_inst->peer_addr;
- if (svc) {
- range_req->interval = svc->ranging_interval;
- /* Limits are in cm from host */
- range_req->ingress = svc->ingress_limit;
- range_req->egress = svc->egress_limit;
- }
- range_req->indication = NAN_RANGING_INDICATE_CONTINUOUS_MASK;
- } else {
- /* range response config */
- sub_cmd->id = htod16(WL_NAN_CMD_RANGE_RESPONSE);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(wl_nan_range_resp_t);
- range_resp = (wl_nan_range_resp_t *)(sub_cmd->data);
- range_resp->range_id = ranging_inst->range_id;
- range_resp->indication = NAN_RANGING_INDICATE_CONTINUOUS_MASK;
- if (accept_req) {
- range_resp->status = NAN_RNG_REQ_ACCEPTED_BY_HOST;
- } else {
- range_resp->status = NAN_RNG_REQ_REJECTED_BY_HOST;
- }
- nan_buf->is_set = true;
- }
- nan_buf_size -= (sub_cmd->len +
- OFFSETOF(bcm_iov_batch_subcmd_t, u.options));
- nan_buf->count++;
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size,
- &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("nan ranging failed ret = %d status = %d\n",
- ret, status));
- ret = (ret == BCME_OK) ? status : ret;
- goto fail;
- }
- WL_TRACE(("nan ranging trigger successful\n"));
- if (range_cmd == NAN_RANGE_REQ_CMD) {
- WL_MEM(("wl_cfgnan_trigger_ranging: Geofence Triggered"
- " peer: " MACDBG ", ind : %d, ingress : %d, egress : %d\n",
- MAC2STRDBG(&ranging_inst->peer_addr), range_req->indication,
- range_req->ingress, range_req->egress));
- } else {
- WL_MEM(("wl_cfgnan_trigger_ranging: Geofence Triggered"
- " peer: " MACDBG ", ind : %d, ingress : %d, egress : %d\n",
- MAC2STRDBG(&ranging_inst->peer_addr), range_resp->indication,
- range_resp->ingress, range_resp->egress));
- }
- /* check the response buff for request */
- if (range_cmd == NAN_RANGE_REQ_CMD) {
- ret = process_resp_buf(resp_buf + WL_NAN_OBUF_DATA_OFFSET,
- &ranging_inst->range_id, WL_NAN_CMD_RANGE_REQUEST);
- WL_INFORM_MEM(("ranging instance returned %d\n", ranging_inst->range_id));
- }
- /* Preventing continuous range requests */
- ranging_inst->range_status = NAN_RANGING_IN_PROGRESS;
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- NAN_DBG_EXIT();
- return ret;
- }
- #endif /* WL_NAN_DISC_CACHE */
- static void *wl_nan_bloom_alloc(void *ctx, uint size)
- {
- uint8 *buf;
- BCM_REFERENCE(ctx);
- buf = kmalloc(size, GFP_KERNEL);
- if (!buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- buf = NULL;
- }
- return buf;
- }
- static void wl_nan_bloom_free(void *ctx, void *buf, uint size)
- {
- BCM_REFERENCE(ctx);
- BCM_REFERENCE(size);
- if (buf) {
- kfree(buf);
- }
- }
- static uint wl_nan_hash(void *ctx, uint index, const uint8 *input, uint input_len)
- {
- uint8* filter_idx = (uint8*)ctx;
- uint8 i = (*filter_idx * WL_NAN_HASHES_PER_BLOOM) + (uint8)index;
- uint b = 0;
- /* Steps 1 and 2 as explained in Section 6.2 */
- /* Concatenate index to input and run CRC32 by calling hndcrc32 twice */
- GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
- b = hndcrc32(&i, sizeof(uint8), CRC32_INIT_VALUE);
- b = hndcrc32((uint8*)input, input_len, b);
- GCC_DIAGNOSTIC_POP();
- /* Obtain the last 2 bytes of the CRC32 output */
- b &= NAN_BLOOM_CRC32_MASK;
- /* Step 3 is completed by bcmbloom functions */
- return b;
- }
- static int wl_nan_bloom_create(bcm_bloom_filter_t **bp, uint *idx, uint size)
- {
- uint i;
- int err;
- err = bcm_bloom_create(wl_nan_bloom_alloc, wl_nan_bloom_free,
- idx, WL_NAN_HASHES_PER_BLOOM, size, bp);
- if (err != BCME_OK) {
- goto exit;
- }
- /* Populate bloom filter with hash functions */
- for (i = 0; i < WL_NAN_HASHES_PER_BLOOM; i++) {
- err = bcm_bloom_add_hash(*bp, wl_nan_hash, &i);
- if (err) {
- WL_ERR(("bcm_bloom_add_hash failed\n"));
- goto exit;
- }
- }
- exit:
- return err;
- }
- static int
- wl_cfgnan_sd_params_handler(struct net_device *ndev,
- nan_discover_cmd_data_t *cmd_data, uint16 cmd_id,
- void *p_buf, uint16 *nan_buf_size)
- {
- s32 ret = BCME_OK;
- uint8 *pxtlv, *srf = NULL, *srf_mac = NULL, *srftmp = NULL;
- uint16 buflen_avail;
- bcm_iov_batch_subcmd_t *sub_cmd = (bcm_iov_batch_subcmd_t*)(p_buf);
- wl_nan_sd_params_t *sd_params = (wl_nan_sd_params_t *)sub_cmd->data;
- uint16 srf_size = 0;
- uint bloom_size, a;
- bcm_bloom_filter_t *bp = NULL;
- /* Bloom filter index default, indicates it has not been set */
- uint bloom_idx = 0xFFFFFFFF;
- uint16 bloom_len = NAN_BLOOM_LENGTH_DEFAULT;
- /* srf_ctrl_size = bloom_len + src_control field */
- uint16 srf_ctrl_size = bloom_len + 1;
- dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(ndev);
- struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
- BCM_REFERENCE(cfg);
- NAN_DBG_ENTER();
- if (cmd_data->period) {
- sd_params->awake_dw = cmd_data->period;
- }
- sd_params->period = 1;
- if (cmd_data->ttl) {
- sd_params->ttl = cmd_data->ttl;
- } else {
- sd_params->ttl = WL_NAN_TTL_UNTIL_CANCEL;
- }
- sd_params->flags = 0;
- sd_params->flags = cmd_data->flags;
- /* Nan Service Based event suppression Flags */
- if (cmd_data->recv_ind_flag) {
- /* BIT0 - If set, host wont rec event "terminated" */
- if (CHECK_BIT(cmd_data->recv_ind_flag, WL_NAN_EVENT_SUPPRESS_TERMINATE_BIT)) {
- sd_params->flags |= WL_NAN_SVC_CTRL_SUPPRESS_EVT_TERMINATED;
- }
- /* BIT1 - If set, host wont receive match expiry evt */
- /* TODO: Exp not yet supported */
- if (CHECK_BIT(cmd_data->recv_ind_flag, WL_NAN_EVENT_SUPPRESS_MATCH_EXP_BIT)) {
- WL_DBG(("Need to add match expiry event\n"));
- }
- /* BIT2 - If set, host wont rec event "receive" */
- if (CHECK_BIT(cmd_data->recv_ind_flag, WL_NAN_EVENT_SUPPRESS_RECEIVE_BIT)) {
- sd_params->flags |= WL_NAN_SVC_CTRL_SUPPRESS_EVT_RECEIVE;
- }
- /* BIT3 - If set, host wont rec event "replied" */
- if (CHECK_BIT(cmd_data->recv_ind_flag, WL_NAN_EVENT_SUPPRESS_REPLIED_BIT)) {
- sd_params->flags |= WL_NAN_SVC_CTRL_SUPPRESS_EVT_REPLIED;
- }
- }
- if (cmd_id == WL_NAN_CMD_SD_PUBLISH) {
- sd_params->instance_id = cmd_data->pub_id;
- if (cmd_data->service_responder_policy) {
- /* Do not disturb avail if dam is supported */
- if (FW_SUPPORTED(dhdp, autodam)) {
- /* Nan Accept policy: Per service basis policy
- * Based on this policy(ALL/NONE), responder side
- * will send ACCEPT/REJECT
- * If set, auto datapath responder will be sent by FW
- */
- sd_params->flags |= WL_NAN_SVC_CTRL_AUTO_DPRESP;
- } else {
- WL_ERR(("svc specifiv auto dp resp is not"
- " supported in non-auto dam fw\n"));
- }
- }
- } else if (cmd_id == WL_NAN_CMD_SD_SUBSCRIBE) {
- sd_params->instance_id = cmd_data->sub_id;
- } else {
- ret = BCME_USAGE_ERROR;
- WL_ERR(("wrong command id = %d \n", cmd_id));
- goto fail;
- }
- if ((cmd_data->svc_hash.dlen == WL_NAN_SVC_HASH_LEN) &&
- (cmd_data->svc_hash.data)) {
- ret = memcpy_s((uint8*)sd_params->svc_hash,
- sizeof(sd_params->svc_hash),
- cmd_data->svc_hash.data,
- cmd_data->svc_hash.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy svc hash\n"));
- goto fail;
- }
- #ifdef WL_NAN_DEBUG
- prhex("hashed svc name", cmd_data->svc_hash.data,
- cmd_data->svc_hash.dlen);
- #endif /* WL_NAN_DEBUG */
- } else {
- ret = BCME_ERROR;
- WL_ERR(("invalid svc hash data or length = %d\n",
- cmd_data->svc_hash.dlen));
- goto fail;
- }
- /* check if ranging support is present in firmware */
- if ((cmd_data->sde_control_flag & NAN_SDE_CF_RANGING_REQUIRED) &&
- !FW_SUPPORTED(dhdp, nanrange)) {
- WL_ERR(("Service requires ranging but fw doesnt support it\n"));
- ret = BCME_UNSUPPORTED;
- goto fail;
- }
- /* Optional parameters: fill the sub_command block with service descriptor attr */
- sub_cmd->id = htod16(cmd_id);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- OFFSETOF(wl_nan_sd_params_t, optional[0]);
- pxtlv = (uint8*)&sd_params->optional[0];
- *nan_buf_size -= sub_cmd->len;
- buflen_avail = *nan_buf_size;
- if (cmd_data->svc_info.data && cmd_data->svc_info.dlen) {
- WL_TRACE(("optional svc_info present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_SD_SVC_INFO,
- cmd_data->svc_info.dlen,
- cmd_data->svc_info.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_SD_SVC_INFO\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->sde_svc_info.data && cmd_data->sde_svc_info.dlen) {
- WL_TRACE(("optional sdea svc_info present, pack it, %d\n",
- cmd_data->sde_svc_info.dlen));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_SD_SDE_SVC_INFO,
- cmd_data->sde_svc_info.dlen,
- cmd_data->sde_svc_info.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack sdea svc info\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->tx_match.dlen) {
- WL_TRACE(("optional tx match filter presnet (len=%d)\n",
- cmd_data->tx_match.dlen));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_CFG_MATCH_TX, cmd_data->tx_match.dlen,
- cmd_data->tx_match.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: failed on xtlv_pack for tx match filter\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->life_count) {
- WL_TRACE(("optional life count is present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size, WL_NAN_XTLV_CFG_SVC_LIFE_COUNT,
- sizeof(cmd_data->life_count), &cmd_data->life_count,
- BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: failed to WL_NAN_XTLV_CFG_SVC_LIFE_COUNT\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->use_srf) {
- uint8 srf_control = 0;
- /* set include bit */
- if (cmd_data->srf_include == true) {
- srf_control |= 0x2;
- }
- if (!ETHER_ISNULLADDR(&cmd_data->mac_list.list) &&
- (cmd_data->mac_list.num_mac_addr
- < NAN_SRF_MAX_MAC)) {
- if (cmd_data->srf_type == SRF_TYPE_SEQ_MAC_ADDR) {
- /* mac list */
- srf_size = (cmd_data->mac_list.num_mac_addr
- * ETHER_ADDR_LEN) + NAN_SRF_CTRL_FIELD_LEN;
- WL_TRACE(("srf size = %d\n", srf_size));
- srf_mac = MALLOCZ(cfg->osh, srf_size);
- if (srf_mac == NULL) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- ret = -ENOMEM;
- goto fail;
- }
- ret = memcpy_s(srf_mac, NAN_SRF_CTRL_FIELD_LEN,
- &srf_control, NAN_SRF_CTRL_FIELD_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy srf control\n"));
- goto fail;
- }
- ret = memcpy_s(srf_mac+1, (srf_size - NAN_SRF_CTRL_FIELD_LEN),
- cmd_data->mac_list.list,
- (srf_size - NAN_SRF_CTRL_FIELD_LEN));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy srf control mac list\n"));
- goto fail;
- }
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_CFG_SR_FILTER, srf_size, srf_mac,
- BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: failed to WL_NAN_XTLV_CFG_SR_FILTER\n",
- __FUNCTION__));
- goto fail;
- }
- } else if (cmd_data->srf_type == SRF_TYPE_BLOOM_FILTER) {
- /* Create bloom filter */
- srf = MALLOCZ(cfg->osh, srf_ctrl_size);
- if (srf == NULL) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- ret = -ENOMEM;
- goto fail;
- }
- /* Bloom filter */
- srf_control |= 0x1;
- /* Instance id must be from 1 to 255, 0 is Reserved */
- if (sd_params->instance_id == NAN_ID_RESERVED) {
- WL_ERR(("Invalid instance id: %d\n",
- sd_params->instance_id));
- ret = BCME_BADARG;
- goto fail;
- }
- if (bloom_idx == 0xFFFFFFFF) {
- bloom_idx = sd_params->instance_id % 4;
- } else {
- WL_ERR(("Invalid bloom_idx\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- srf_control |= bloom_idx << 2;
- ret = wl_nan_bloom_create(&bp, &bloom_idx, bloom_len);
- if (unlikely(ret)) {
- WL_ERR(("%s: Bloom create failed\n", __FUNCTION__));
- goto fail;
- }
- srftmp = cmd_data->mac_list.list;
- for (a = 0;
- a < cmd_data->mac_list.num_mac_addr; a++) {
- ret = bcm_bloom_add_member(bp, srftmp, ETHER_ADDR_LEN);
- if (unlikely(ret)) {
- WL_ERR(("%s: Cannot add to bloom filter\n",
- __FUNCTION__));
- goto fail;
- }
- srftmp += ETHER_ADDR_LEN;
- }
- ret = memcpy_s(srf, NAN_SRF_CTRL_FIELD_LEN,
- &srf_control, NAN_SRF_CTRL_FIELD_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy srf control\n"));
- goto fail;
- }
- ret = bcm_bloom_get_filter_data(bp, bloom_len,
- (srf + NAN_SRF_CTRL_FIELD_LEN),
- &bloom_size);
- if (unlikely(ret)) {
- WL_ERR(("%s: Cannot get filter data\n", __FUNCTION__));
- goto fail;
- }
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_CFG_SR_FILTER, srf_ctrl_size,
- srf, BCM_XTLV_OPTION_ALIGN32);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to pack SR FILTER data, ret = %d\n", ret));
- goto fail;
- }
- } else {
- WL_ERR(("Invalid SRF Type = %d !!!\n",
- cmd_data->srf_type));
- goto fail;
- }
- } else {
- WL_ERR(("Invalid MAC Addr/Too many mac addr = %d !!!\n",
- cmd_data->mac_list.num_mac_addr));
- goto fail;
- }
- }
- if (cmd_data->rx_match.dlen) {
- WL_TRACE(("optional rx match filter is present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_CFG_MATCH_RX, cmd_data->rx_match.dlen,
- cmd_data->rx_match.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: failed on xtlv_pack for rx match filter\n", __func__));
- goto fail;
- }
- }
- /* Security elements */
- if (cmd_data->csid) {
- WL_TRACE(("Cipher suite type is present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_CFG_SEC_CSID, sizeof(nan_sec_csid_e),
- (uint8*)&cmd_data->csid, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack on csid\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->ndp_cfg.security_cfg) {
- if ((cmd_data->key_type == NAN_SECURITY_KEY_INPUT_PMK) ||
- (cmd_data->key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE)) {
- if (cmd_data->key.data && cmd_data->key.dlen) {
- WL_TRACE(("optional pmk present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_CFG_SEC_PMK, cmd_data->key.dlen,
- cmd_data->key.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_CFG_SEC_PMK\n",
- __FUNCTION__));
- goto fail;
- }
- }
- } else {
- WL_ERR(("Invalid security key type\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- }
- if (cmd_data->scid.data && cmd_data->scid.dlen) {
- WL_TRACE(("optional scid present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size, WL_NAN_XTLV_CFG_SEC_SCID,
- cmd_data->scid.dlen, cmd_data->scid.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_CFG_SEC_SCID\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->sde_control_config) {
- ret = bcm_pack_xtlv_entry(&pxtlv, nan_buf_size,
- WL_NAN_XTLV_SD_SDE_CONTROL,
- sizeof(uint16), (uint8*)&cmd_data->sde_control_flag,
- BCM_XTLV_OPTION_ALIGN32);
- if (ret != BCME_OK) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_SD_SDE_CONTROL\n", __FUNCTION__));
- goto fail;
- }
- }
- sub_cmd->len += (buflen_avail - *nan_buf_size);
- fail:
- if (srf) {
- MFREE(cfg->osh, srf, srf_ctrl_size);
- }
- if (srf_mac) {
- MFREE(cfg->osh, srf_mac, srf_size);
- }
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_aligned_data_size_of_opt_disc_params(uint16 *data_size, nan_discover_cmd_data_t *cmd_data)
- {
- s32 ret = BCME_OK;
- if (cmd_data->svc_info.dlen)
- *data_size += ALIGN_SIZE(cmd_data->svc_info.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->sde_svc_info.dlen)
- *data_size += ALIGN_SIZE(cmd_data->sde_svc_info.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->tx_match.dlen)
- *data_size += ALIGN_SIZE(cmd_data->tx_match.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->rx_match.dlen)
- *data_size += ALIGN_SIZE(cmd_data->rx_match.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->use_srf) {
- if (cmd_data->srf_type == SRF_TYPE_SEQ_MAC_ADDR) {
- *data_size += (cmd_data->mac_list.num_mac_addr * ETHER_ADDR_LEN)
- + NAN_SRF_CTRL_FIELD_LEN;
- } else { /* Bloom filter type */
- *data_size += NAN_BLOOM_LENGTH_DEFAULT + 1;
- }
- *data_size += ALIGN_SIZE(*data_size + NAN_XTLV_ID_LEN_SIZE, 4);
- }
- if (cmd_data->csid)
- *data_size += ALIGN_SIZE(sizeof(nan_sec_csid_e) + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->key.dlen)
- *data_size += ALIGN_SIZE(cmd_data->key.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->scid.dlen)
- *data_size += ALIGN_SIZE(cmd_data->scid.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->sde_control_config)
- *data_size += ALIGN_SIZE(sizeof(uint16) + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->life_count)
- *data_size += ALIGN_SIZE(sizeof(cmd_data->life_count) + NAN_XTLV_ID_LEN_SIZE, 4);
- return ret;
- }
- static int
- wl_cfgnan_aligned_data_size_of_opt_dp_params(uint16 *data_size, nan_datapath_cmd_data_t *cmd_data)
- {
- s32 ret = BCME_OK;
- if (cmd_data->svc_info.dlen)
- *data_size += ALIGN_SIZE(cmd_data->svc_info.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->key.dlen)
- *data_size += ALIGN_SIZE(cmd_data->key.dlen + NAN_XTLV_ID_LEN_SIZE, 4);
- if (cmd_data->csid)
- *data_size += ALIGN_SIZE(sizeof(nan_sec_csid_e) + NAN_XTLV_ID_LEN_SIZE, 4);
- *data_size += ALIGN_SIZE(WL_NAN_SVC_HASH_LEN + NAN_XTLV_ID_LEN_SIZE, 4);
- return ret;
- }
- int
- wl_cfgnan_svc_get_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, uint16 cmd_id, nan_discover_cmd_data_t *cmd_data)
- {
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- uint32 instance_id;
- s32 ret = BCME_OK;
- bcm_iov_batch_buf_t *nan_buf = NULL;
- uint8 *resp_buf = NULL;
- uint16 data_size = WL_NAN_OBUF_DATA_OFFSET + sizeof(instance_id);
- NAN_DBG_ENTER();
- nan_buf = MALLOCZ(cfg->osh, data_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- resp_buf = MALLOCZ(cfg->osh, NAN_IOCTL_BUF_SIZE_LARGE);
- if (!resp_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 1;
- /* check if service is present */
- nan_buf->is_set = false;
- sub_cmd = (bcm_iov_batch_subcmd_t*)(&nan_buf->cmds[0]);
- if (cmd_id == WL_NAN_CMD_SD_PUBLISH) {
- instance_id = cmd_data->pub_id;
- } else if (cmd_id == WL_NAN_CMD_SD_SUBSCRIBE) {
- instance_id = cmd_data->sub_id;
- } else {
- ret = BCME_USAGE_ERROR;
- WL_ERR(("wrong command id = %u\n", cmd_id));
- goto fail;
- }
- /* Fill the sub_command block */
- sub_cmd->id = htod16(cmd_id);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(instance_id);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- ret = memcpy_s(sub_cmd->data, (data_size - WL_NAN_OBUF_DATA_OFFSET),
- &instance_id, sizeof(instance_id));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy instance id, ret = %d\n", ret));
- goto fail;
- }
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, data_size,
- &(cmd_data->status), resp_buf, NAN_IOCTL_BUF_SIZE_LARGE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan svc check failed ret = %d status = %d\n", ret, cmd_data->status));
- goto fail;
- } else {
- WL_DBG(("nan svc check successful..proceed to update\n"));
- }
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, data_size);
- }
- if (resp_buf) {
- MFREE(cfg->osh, resp_buf, NAN_IOCTL_BUF_SIZE_LARGE);
- }
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_svc_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, uint16 cmd_id, nan_discover_cmd_data_t *cmd_data)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_buf_t *nan_buf = NULL;
- uint16 nan_buf_size;
- uint8 *resp_buf = NULL;
- /* Considering fixed params */
- uint16 data_size = WL_NAN_OBUF_DATA_OFFSET +
- OFFSETOF(wl_nan_sd_params_t, optional[0]);
- if (cmd_data->svc_update) {
- ret = wl_cfgnan_svc_get_handler(ndev, cfg, cmd_id, cmd_data);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to update svc handler, ret = %d\n", ret));
- goto fail;
- } else {
- /* Ignoring any other svc get error */
- if (cmd_data->status == WL_NAN_E_BAD_INSTANCE) {
- WL_ERR(("Bad instance status, failed to update svc handler\n"));
- goto fail;
- }
- }
- }
- ret = wl_cfgnan_aligned_data_size_of_opt_disc_params(&data_size, cmd_data);
- if (unlikely(ret)) {
- WL_ERR(("Failed to get alligned size of optional params\n"));
- goto fail;
- }
- nan_buf_size = data_size;
- NAN_DBG_ENTER();
- nan_buf = MALLOCZ(cfg->osh, data_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- resp_buf = MALLOCZ(cfg->osh, data_size + NAN_IOVAR_NAME_SIZE);
- if (!resp_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf->is_set = true;
- ret = wl_cfgnan_sd_params_handler(ndev, cmd_data, cmd_id,
- &nan_buf->cmds[0], &nan_buf_size);
- if (unlikely(ret)) {
- WL_ERR((" Service discovery params handler failed, ret = %d\n", ret));
- goto fail;
- }
- nan_buf->count++;
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, data_size,
- &(cmd_data->status), resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- if (cmd_data->svc_update && (cmd_data->status == BCME_DATA_NOTFOUND)) {
- /* return OK if update tlv data is not present
- * which means nothing to update
- */
- cmd_data->status = BCME_OK;
- }
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan svc failed ret = %d status = %d\n", ret, cmd_data->status));
- goto fail;
- } else {
- WL_DBG(("nan svc successful\n"));
- #ifdef WL_NAN_DISC_CACHE
- ret = wl_cfgnan_cache_svc_info(cfg, cmd_data, cmd_id, cmd_data->svc_update);
- if (ret < 0) {
- WL_ERR(("%s: fail to cache svc info, ret=%d\n",
- __FUNCTION__, ret));
- goto fail;
- }
- #endif /* WL_NAN_DISC_CACHE */
- }
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, data_size);
- }
- if (resp_buf) {
- MFREE(cfg->osh, resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- }
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_publish_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_discover_cmd_data_t *cmd_data)
- {
- int ret = BCME_OK;
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- /*
- * proceed only if mandatory arguments are present - subscriber id,
- * service hash
- */
- if ((!cmd_data->pub_id) || (!cmd_data->svc_hash.data) ||
- (!cmd_data->svc_hash.dlen)) {
- WL_ERR(("mandatory arguments are not present\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- ret = wl_cfgnan_svc_handler(ndev, cfg, WL_NAN_CMD_SD_PUBLISH, cmd_data);
- if (ret < 0) {
- WL_ERR(("%s: fail to handle pub, ret=%d\n", __FUNCTION__, ret));
- goto fail;
- }
- WL_INFORM_MEM(("[NAN] Service published for instance id:%d\n", cmd_data->pub_id));
- fail:
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_subscribe_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_discover_cmd_data_t *cmd_data)
- {
- int ret = BCME_OK;
- #ifdef WL_NAN_DISC_CACHE
- nan_svc_info_t *svc_info;
- uint8 upd_ranging_required;
- #endif /* WL_NAN_DISC_CACHE */
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- /*
- * proceed only if mandatory arguments are present - subscriber id,
- * service hash
- */
- if ((!cmd_data->sub_id) || (!cmd_data->svc_hash.data) ||
- (!cmd_data->svc_hash.dlen)) {
- WL_ERR(("mandatory arguments are not present\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- /* Check for ranging sessions if any */
- if (cmd_data->svc_update) {
- #ifdef WL_NAN_DISC_CACHE
- svc_info = wl_cfgnan_get_svc_inst(cfg, cmd_data->sub_id, 0);
- if (svc_info) {
- wl_cfgnan_clear_svc_ranging_inst(cfg, cmd_data->sub_id);
- /* terminate ranging sessions for this svc, avoid clearing svc cache */
- wl_cfgnan_terminate_ranging_sessions(ndev, cfg, cmd_data->sub_id);
- WL_DBG(("Ranging sessions terminated for svc update\n"));
- upd_ranging_required = !!(cmd_data->sde_control_flag &
- NAN_SDE_CF_RANGING_REQUIRED);
- if ((svc_info->ranging_required ^ upd_ranging_required) ||
- (svc_info->ingress_limit != cmd_data->ingress_limit) ||
- (svc_info->egress_limit != cmd_data->egress_limit)) {
- /* Clear cache info in Firmware */
- ret = wl_cfgnan_clear_disc_cache(cfg, cmd_data->sub_id);
- if (ret != BCME_OK) {
- WL_ERR(("couldn't send clear cache to FW \n"));
- goto fail;
- }
- /* Invalidate local cache info */
- wl_cfgnan_remove_disc_result(cfg, cmd_data->sub_id);
- }
- }
- #endif /* WL_NAN_DISC_CACHE */
- }
- ret = wl_cfgnan_svc_handler(ndev, cfg, WL_NAN_CMD_SD_SUBSCRIBE, cmd_data);
- if (ret < 0) {
- WL_ERR(("%s: fail to handle svc, ret=%d\n", __FUNCTION__, ret));
- goto fail;
- }
- WL_INFORM_MEM(("[NAN] Service subscribed for instance id:%d\n", cmd_data->sub_id));
- fail:
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_cancel_handler(nan_discover_cmd_data_t *cmd_data,
- uint16 cmd_id, void *p_buf, uint16 *nan_buf_size)
- {
- s32 ret = BCME_OK;
- NAN_DBG_ENTER();
- if (p_buf != NULL) {
- bcm_iov_batch_subcmd_t *sub_cmd = (bcm_iov_batch_subcmd_t*)(p_buf);
- wl_nan_instance_id_t instance_id;
- if (cmd_id == WL_NAN_CMD_SD_CANCEL_PUBLISH) {
- instance_id = cmd_data->pub_id;
- } else if (cmd_id == WL_NAN_CMD_SD_CANCEL_SUBSCRIBE) {
- instance_id = cmd_data->sub_id;
- } else {
- ret = BCME_USAGE_ERROR;
- WL_ERR(("wrong command id = %u\n", cmd_id));
- goto fail;
- }
- /* Fill the sub_command block */
- sub_cmd->id = htod16(cmd_id);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(instance_id);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- ret = memcpy_s(sub_cmd->data, *nan_buf_size,
- &instance_id, sizeof(instance_id));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy instance id, ret = %d\n", ret));
- goto fail;
- }
- /* adjust iov data len to the end of last data record */
- *nan_buf_size -= (sub_cmd->len +
- OFFSETOF(bcm_iov_batch_subcmd_t, u.options));
- WL_INFORM_MEM(("[NAN] Service with instance id:%d cancelled\n", instance_id));
- } else {
- WL_ERR(("nan_iov_buf is NULL\n"));
- ret = BCME_ERROR;
- goto fail;
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_cancel_pub_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_discover_cmd_data_t *cmd_data)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- /* proceed only if mandatory argument is present - publisher id */
- if (!cmd_data->pub_id) {
- WL_ERR(("mandatory argument is not present\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- #ifdef WL_NAN_DISC_CACHE
- wl_cfgnan_clear_svc_cache(cfg, cmd_data->pub_id);
- #endif /* WL_NAN_DISC_CACHE */
- ret = wl_cfgnan_cancel_handler(cmd_data, WL_NAN_CMD_SD_CANCEL_PUBLISH,
- &nan_buf->cmds[0], &nan_buf_size);
- if (unlikely(ret)) {
- WL_ERR(("cancel publish failed\n"));
- goto fail;
- }
- nan_buf->is_set = true;
- nan_buf->count++;
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size,
- &(cmd_data->status),
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan cancel publish failed ret = %d status = %d\n",
- ret, cmd_data->status));
- goto fail;
- }
- WL_DBG(("nan cancel publish successfull\n"));
- wl_cfgnan_remove_inst_id(cfg, cmd_data->pub_id);
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_cancel_sub_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_discover_cmd_data_t *cmd_data)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- /* proceed only if mandatory argument is present - subscriber id */
- if (!cmd_data->sub_id) {
- WL_ERR(("mandatory argument is not present\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- #ifdef WL_NAN_DISC_CACHE
- /* terminate ranging sessions for this svc */
- wl_cfgnan_clear_svc_ranging_inst(cfg, cmd_data->sub_id);
- wl_cfgnan_terminate_ranging_sessions(ndev, cfg, cmd_data->sub_id);
- /* clear svc cache for the service */
- wl_cfgnan_clear_svc_cache(cfg, cmd_data->sub_id);
- wl_cfgnan_remove_disc_result(cfg, cmd_data->sub_id);
- #endif /* WL_NAN_DISC_CACHE */
- ret = wl_cfgnan_cancel_handler(cmd_data, WL_NAN_CMD_SD_CANCEL_SUBSCRIBE,
- &nan_buf->cmds[0], &nan_buf_size);
- if (unlikely(ret)) {
- WL_ERR(("cancel subscribe failed\n"));
- goto fail;
- }
- nan_buf->is_set = true;
- nan_buf->count++;
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size,
- &(cmd_data->status),
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan cancel subscribe failed ret = %d status = %d\n",
- ret, cmd_data->status));
- goto fail;
- }
- WL_DBG(("subscribe cancel successfull\n"));
- wl_cfgnan_remove_inst_id(cfg, cmd_data->sub_id);
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_transmit_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_discover_cmd_data_t *cmd_data)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_buf_t *nan_buf = NULL;
- wl_nan_sd_transmit_t *sd_xmit = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- bool is_lcl_id = FALSE;
- bool is_dest_id = FALSE;
- bool is_dest_mac = FALSE;
- uint16 buflen_avail;
- uint8 *pxtlv;
- uint16 nan_buf_size;
- uint8 *resp_buf = NULL;
- /* Considering fixed params */
- uint16 data_size = WL_NAN_OBUF_DATA_OFFSET +
- OFFSETOF(wl_nan_sd_transmit_t, opt_tlv);
- data_size = ALIGN_SIZE(data_size, 4);
- ret = wl_cfgnan_aligned_data_size_of_opt_disc_params(&data_size, cmd_data);
- if (unlikely(ret)) {
- WL_ERR(("Failed to get alligned size of optional params\n"));
- goto fail;
- }
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- nan_buf_size = data_size;
- nan_buf = MALLOCZ(cfg->osh, data_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- resp_buf = MALLOCZ(cfg->osh, data_size + NAN_IOVAR_NAME_SIZE);
- if (!resp_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- /* nan transmit */
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- /*
- * proceed only if mandatory arguments are present - subscriber id,
- * publisher id, mac address
- */
- if ((!cmd_data->local_id) || (!cmd_data->remote_id) ||
- ETHER_ISNULLADDR(&cmd_data->mac_addr.octet)) {
- WL_ERR(("mandatory arguments are not present\n"));
- ret = -EINVAL;
- goto fail;
- }
- sub_cmd = (bcm_iov_batch_subcmd_t*)(&nan_buf->cmds[0]);
- sd_xmit = (wl_nan_sd_transmit_t *)(sub_cmd->data);
- /* local instance id must be from 1 to 255, 0 is reserved */
- if (cmd_data->local_id == NAN_ID_RESERVED) {
- WL_ERR(("Invalid local instance id: %d\n", cmd_data->local_id));
- ret = BCME_BADARG;
- goto fail;
- }
- sd_xmit->local_service_id = cmd_data->local_id;
- is_lcl_id = TRUE;
- /* remote instance id must be from 1 to 255, 0 is reserved */
- if (cmd_data->remote_id == NAN_ID_RESERVED) {
- WL_ERR(("Invalid remote instance id: %d\n", cmd_data->remote_id));
- ret = BCME_BADARG;
- goto fail;
- }
- sd_xmit->requestor_service_id = cmd_data->remote_id;
- is_dest_id = TRUE;
- if (!ETHER_ISNULLADDR(&cmd_data->mac_addr.octet)) {
- ret = memcpy_s(&sd_xmit->destination_addr, ETHER_ADDR_LEN,
- &cmd_data->mac_addr, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy dest mac address\n"));
- goto fail;
- }
- } else {
- WL_ERR(("Invalid ether addr provided\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- is_dest_mac = TRUE;
- if (cmd_data->priority) {
- sd_xmit->priority = cmd_data->priority;
- }
- sd_xmit->token = cmd_data->token;
- if (cmd_data->recv_ind_flag) {
- /* BIT0 - If set, host wont rec event "txs" */
- if (CHECK_BIT(cmd_data->recv_ind_flag,
- WL_NAN_EVENT_SUPPRESS_FOLLOWUP_RECEIVE_BIT)) {
- sd_xmit->flags = WL_NAN_FUP_SUPR_EVT_TXS;
- }
- }
- /* Optional parameters: fill the sub_command block with service descriptor attr */
- sub_cmd->id = htod16(WL_NAN_CMD_SD_TRANSMIT);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- OFFSETOF(wl_nan_sd_transmit_t, opt_tlv);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- pxtlv = (uint8 *)&sd_xmit->opt_tlv;
- nan_buf_size -= (sub_cmd->len +
- OFFSETOF(bcm_iov_batch_subcmd_t, u.options));
- buflen_avail = nan_buf_size;
- if (cmd_data->svc_info.data && cmd_data->svc_info.dlen) {
- bcm_xtlv_t *pxtlv_svc_info = (bcm_xtlv_t *)pxtlv;
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_SD_SVC_INFO, cmd_data->svc_info.dlen,
- cmd_data->svc_info.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack on bcm_pack_xtlv_entry, ret=%d\n",
- __FUNCTION__, ret));
- goto fail;
- }
- /* 0xFF is max length for svc_info */
- if (pxtlv_svc_info->len > 0xFF) {
- WL_ERR(("Invalid service info length %d\n",
- (pxtlv_svc_info->len)));
- ret = BCME_USAGE_ERROR;
- goto fail;
- }
- sd_xmit->opt_len = (uint8)(pxtlv_svc_info->len);
- }
- if (cmd_data->sde_svc_info.data && cmd_data->sde_svc_info.dlen) {
- WL_TRACE(("optional sdea svc_info present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_SD_SDE_SVC_INFO, cmd_data->sde_svc_info.dlen,
- cmd_data->sde_svc_info.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack sdea svc info\n", __FUNCTION__));
- goto fail;
- }
- }
- /* Check if all mandatory params are provided */
- if (is_lcl_id && is_dest_id && is_dest_mac) {
- nan_buf->count++;
- sub_cmd->len += (buflen_avail - nan_buf_size);
- } else {
- WL_ERR(("Missing parameters\n"));
- ret = BCME_USAGE_ERROR;
- }
- nan_buf->is_set = TRUE;
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, data_size,
- &(cmd_data->status), resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan transmit failed for token %d ret = %d status = %d\n",
- sd_xmit->token, ret, cmd_data->status));
- goto fail;
- }
- WL_INFORM_MEM(("nan transmit successful for token %d\n", sd_xmit->token));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, data_size);
- }
- if (resp_buf) {
- MFREE(cfg->osh, resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- }
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_get_capability(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_hal_capabilities_t *capabilities)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- wl_nan_fw_cap_t *fw_cap = NULL;
- uint16 subcmd_len;
- uint32 status;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd_resp = NULL;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- const bcm_xtlv_t *xtlv;
- uint16 type = 0;
- int len = 0;
- NAN_DBG_ENTER();
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(uint8 *)(&nan_buf->cmds[0]);
- ret = wl_cfg_nan_check_cmd_len(nan_buf_size,
- sizeof(*fw_cap), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- fw_cap = (wl_nan_fw_cap_t *)sub_cmd->data;
- sub_cmd->id = htod16(WL_NAN_CMD_GEN_FW_CAP);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(*fw_cap);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- nan_buf_size -= subcmd_len;
- nan_buf->count = 1;
- nan_buf->is_set = false;
- memset(resp_buf, 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("get nan fw cap failed ret %d status %d \n",
- ret, status));
- goto fail;
- }
- sub_cmd_resp = &((bcm_iov_batch_buf_t *)(resp_buf))->cmds[0];
- /* check the response buff */
- xtlv = ((const bcm_xtlv_t *)&sub_cmd_resp->data[0]);
- if (!xtlv) {
- ret = BCME_NOTFOUND;
- WL_ERR(("xtlv not found: err = %d\n", ret));
- goto fail;
- }
- bcm_xtlv_unpack_xtlv(xtlv, &type, (uint16*)&len, NULL, BCM_XTLV_OPTION_ALIGN32);
- do
- {
- switch (type) {
- case WL_NAN_XTLV_GEN_FW_CAP:
- if (len > sizeof(wl_nan_fw_cap_t)) {
- ret = BCME_BADARG;
- goto fail;
- }
- GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
- fw_cap = (wl_nan_fw_cap_t*)xtlv->data;
- GCC_DIAGNOSTIC_POP();
- break;
- default:
- WL_ERR(("Unknown xtlv: id %u\n", type));
- ret = BCME_ERROR;
- break;
- }
- if (ret != BCME_OK) {
- goto fail;
- }
- } while ((xtlv = bcm_next_xtlv(xtlv, &len, BCM_XTLV_OPTION_ALIGN32)));
- memset(capabilities, 0, sizeof(nan_hal_capabilities_t));
- capabilities->max_publishes = fw_cap->max_svc_publishes;
- capabilities->max_subscribes = fw_cap->max_svc_subscribes;
- capabilities->max_ndi_interfaces = fw_cap->max_lcl_ndi_interfaces;
- capabilities->max_ndp_sessions = fw_cap->max_ndp_sessions;
- capabilities->max_concurrent_nan_clusters = fw_cap->max_concurrent_nan_clusters;
- capabilities->max_service_name_len = fw_cap->max_service_name_len;
- capabilities->max_match_filter_len = fw_cap->max_match_filter_len;
- capabilities->max_total_match_filter_len = fw_cap->max_total_match_filter_len;
- capabilities->max_service_specific_info_len = fw_cap->max_service_specific_info_len;
- capabilities->max_app_info_len = fw_cap->max_app_info_len;
- capabilities->max_sdea_service_specific_info_len = fw_cap->max_sdea_svc_specific_info_len;
- capabilities->max_queued_transmit_followup_msgs = fw_cap->max_queued_tx_followup_msgs;
- capabilities->max_subscribe_address = fw_cap->max_subscribe_address;
- capabilities->is_ndp_security_supported = fw_cap->is_ndp_security_supported;
- capabilities->ndp_supported_bands = fw_cap->ndp_supported_bands;
- capabilities->cipher_suites_supported = fw_cap->cipher_suites_supported_mask;
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_get_capablities_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_hal_capabilities_t *capabilities)
- {
- s32 ret = BCME_OK;
- dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(ndev);
- NAN_DBG_ENTER();
- /* Do not query fw about nan if feature is not supported */
- if (!FW_SUPPORTED(dhdp, nan)) {
- WL_DBG(("NAN is not supported\n"));
- return ret;
- }
- if (cfg->nan_init_state) {
- ret = wl_cfgnan_get_capability(ndev, cfg, capabilities);
- if (ret != BCME_OK) {
- WL_ERR(("NAN init state: %d, failed to get capability from FW[%d]\n",
- cfg->nan_init_state, ret));
- goto exit;
- }
- } else {
- /* Initialize NAN before sending iovar */
- WL_ERR(("Initializing NAN\n"));
- ret = wl_cfgnan_init(cfg);
- if (ret != BCME_OK) {
- WL_ERR(("failed to initialize NAN[%d]\n", ret));
- goto fail;
- }
- ret = wl_cfgnan_get_capability(ndev, cfg, capabilities);
- if (ret != BCME_OK) {
- WL_ERR(("NAN init state: %d, failed to get capability from FW[%d]\n",
- cfg->nan_init_state, ret));
- goto exit;
- }
- WL_ERR(("De-Initializing NAN\n"));
- ret = wl_cfgnan_deinit(cfg, dhdp->up);
- if (ret != BCME_OK) {
- WL_ERR(("failed to de-initialize NAN[%d]\n", ret));
- goto fail;
- }
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- exit:
- /* Keeping backward campatibility */
- capabilities->max_concurrent_nan_clusters = MAX_CONCURRENT_NAN_CLUSTERS;
- capabilities->max_publishes = MAX_PUBLISHES;
- capabilities->max_subscribes = MAX_SUBSCRIBES;
- capabilities->max_service_name_len = MAX_SVC_NAME_LEN;
- capabilities->max_match_filter_len = MAX_MATCH_FILTER_LEN;
- capabilities->max_total_match_filter_len = MAX_TOTAL_MATCH_FILTER_LEN;
- capabilities->max_service_specific_info_len = NAN_MAX_SERVICE_SPECIFIC_INFO_LEN;
- capabilities->max_ndi_interfaces = MAX_NDI_INTERFACES;
- capabilities->max_ndp_sessions = MAX_NDP_SESSIONS;
- capabilities->max_app_info_len = MAX_APP_INFO_LEN;
- capabilities->max_queued_transmit_followup_msgs = MAX_QUEUED_TX_FOLLOUP_MSGS;
- capabilities->max_sdea_service_specific_info_len = MAX_SDEA_SVC_INFO_LEN;
- capabilities->max_subscribe_address = MAX_SUBSCRIBE_ADDRESS;
- capabilities->cipher_suites_supported = WL_NAN_CIPHER_SUITE_SHARED_KEY_128_MASK;
- capabilities->max_scid_len = MAX_SCID_LEN;
- capabilities->is_ndp_security_supported = true;
- capabilities->ndp_supported_bands = NDP_SUPPORTED_BANDS;
- ret = BCME_OK;
- NAN_DBG_EXIT();
- return ret;
- }
- bool wl_cfgnan_check_state(struct bcm_cfg80211 *cfg)
- {
- return cfg->nan_enable;
- }
- int
- wl_cfgnan_init(struct bcm_cfg80211 *cfg)
- {
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint32 status;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- uint8 buf[NAN_IOCTL_BUF_SIZE];
- bcm_iov_batch_buf_t *nan_buf = (bcm_iov_batch_buf_t*)buf;
- NAN_DBG_ENTER();
- if (cfg->nan_init_state) {
- WL_ERR(("nan initialized/nmi exists\n"));
- return BCME_OK;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- ret = wl_cfgnan_init_handler(&nan_buf->cmds[0], &nan_buf_size, true);
- if (unlikely(ret)) {
- WL_ERR(("init handler sub_cmd set failed\n"));
- goto fail;
- }
- nan_buf->count++;
- nan_buf->is_set = true;
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(bcmcfg_to_prmry_ndev(cfg), cfg,
- nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("nan init handler failed ret %d status %d\n",
- ret, status));
- goto fail;
- }
- #ifdef WL_NAN_DISC_CACHE
- /* malloc for disc result */
- cfg->nan_disc_cache = MALLOCZ(cfg->osh,
- NAN_MAX_CACHE_DISC_RESULT * sizeof(nan_disc_result_cache));
- if (!cfg->nan_disc_cache) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- #endif /* WL_NAN_DISC_CACHE */
- cfg->nan_init_state = true;
- return ret;
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_deinit(struct bcm_cfg80211 *cfg, uint8 busstate)
- {
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint32 status;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- uint8 buf[NAN_IOCTL_BUF_SIZE];
- bcm_iov_batch_buf_t *nan_buf = (bcm_iov_batch_buf_t*)buf;
- uint8 i = 0;
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- if (!cfg->nan_init_state) {
- WL_ERR(("nan is not initialized/nmi doesnt exists\n"));
- ret = BCME_OK;
- goto fail;
- }
- if (busstate != DHD_BUS_DOWN) {
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- WL_DBG(("nan deinit\n"));
- ret = wl_cfgnan_init_handler(&nan_buf->cmds[0], &nan_buf_size, false);
- if (unlikely(ret)) {
- WL_ERR(("deinit handler sub_cmd set failed\n"));
- } else {
- nan_buf->count++;
- nan_buf->is_set = true;
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(cfg->wdev->netdev, cfg,
- nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("nan init handler failed ret %d status %d\n",
- ret, status));
- }
- }
- }
- cfg->nan_dp_mask = 0;
- cfg->nan_init_state = false;
- #ifdef WL_NAN_DISC_CACHE
- if (cfg->nan_disc_cache) {
- for (i = 0; i < NAN_MAX_CACHE_DISC_RESULT; i++) {
- if (cfg->nan_disc_cache[i].tx_match_filter.data) {
- MFREE(cfg->osh, cfg->nan_disc_cache[i].tx_match_filter.data,
- cfg->nan_disc_cache[i].tx_match_filter.dlen);
- }
- if (cfg->nan_disc_cache[i].svc_info.data) {
- MFREE(cfg->osh, cfg->nan_disc_cache[i].svc_info.data,
- cfg->nan_disc_cache[i].svc_info.dlen);
- }
- }
- MFREE(cfg->osh, cfg->nan_disc_cache,
- NAN_MAX_CACHE_DISC_RESULT * sizeof(nan_disc_result_cache));
- cfg->nan_disc_cache = NULL;
- }
- cfg->nan_disc_count = 0;
- memset_s(cfg->svc_info, NAN_MAX_SVC_INST * sizeof(nan_svc_info_t),
- 0, NAN_MAX_SVC_INST * sizeof(nan_svc_info_t));
- memset_s(cfg->nan_ranging_info, NAN_MAX_RANGING_INST * sizeof(nan_ranging_inst_t),
- 0, NAN_MAX_RANGING_INST * sizeof(nan_ranging_inst_t));
- #endif /* WL_NAN_DISC_CACHE */
- fail:
- if (!cfg->nancfg.mac_rand && !ETHER_ISNULLADDR(cfg->nan_nmi_mac)) {
- wl_release_vif_macaddr(cfg, cfg->nan_nmi_mac, WL_IF_TYPE_NAN_NMI);
- }
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- static int
- wl_cfgnan_get_ndi_macaddr(struct bcm_cfg80211 *cfg, u8* mac_addr)
- {
- int i = 0;
- int ret = BCME_OK;
- bool rand_mac = cfg->nancfg.mac_rand;
- BCM_REFERENCE(i);
- if (rand_mac) {
- /* ensure nmi != ndi */
- do {
- RANDOM_BYTES(mac_addr, ETHER_ADDR_LEN);
- /* restore mcast and local admin bits to 0 and 1 */
- ETHER_SET_UNICAST(mac_addr);
- ETHER_SET_LOCALADDR(mac_addr);
- i++;
- if (i == NAN_RAND_MAC_RETRIES) {
- break;
- }
- } while (eacmp(cfg->nan_nmi_mac, mac_addr) == 0);
- if (i == NAN_RAND_MAC_RETRIES) {
- if (eacmp(cfg->nan_nmi_mac, mac_addr) == 0) {
- WL_ERR(("\nCouldn't generate rand NDI which != NMI\n"));
- ret = BCME_NORESOURCE;
- goto fail;
- }
- }
- } else {
- if (wl_get_vif_macaddr(cfg, WL_IF_TYPE_NAN,
- mac_addr) != BCME_OK) {
- ret = -EINVAL;
- WL_ERR(("Failed to get mac addr for NDI\n"));
- goto fail;
- }
- }
- fail:
- return ret;
- }
- int
- wl_cfgnan_data_path_iface_create_delete_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, char *ifname, uint16 type, uint8 busstate)
- {
- u8 mac_addr[ETH_ALEN];
- s32 ret = BCME_OK;
- s32 idx;
- struct wireless_dev *wdev;
- NAN_DBG_ENTER();
- if (busstate != DHD_BUS_DOWN) {
- if (type == NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE) {
- if ((idx = wl_cfgnan_get_ndi_idx(cfg)) < 0) {
- WL_ERR(("No free idx for NAN NDI\n"));
- ret = BCME_NORESOURCE;
- goto fail;
- }
- ret = wl_cfgnan_get_ndi_macaddr(cfg, mac_addr);
- if (ret != BCME_OK) {
- WL_ERR(("Couldn't get mac addr for NDI ret %d\n", ret));
- goto fail;
- }
- wdev = wl_cfg80211_add_if(cfg, ndev, WL_IF_TYPE_NAN,
- ifname, mac_addr);
- if (!wdev) {
- ret = -ENODEV;
- WL_ERR(("Failed to create NDI iface = %s, wdev is NULL\n", ifname));
- goto fail;
- }
- /* Store the iface name to pub data so that it can be used
- * during NAN enable
- */
- wl_cfgnan_add_ndi_data(cfg, idx, ifname);
- cfg->nancfg.ndi[idx].created = true;
- /* Store nan ndev */
- cfg->nancfg.ndi[idx].nan_ndev = wdev_to_ndev(wdev);
- } else if (type == NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE) {
- ret = wl_cfg80211_del_if(cfg, ndev, NULL, ifname);
- if (ret == BCME_OK) {
- if (wl_cfgnan_del_ndi_data(cfg, ifname) < 0) {
- WL_ERR(("Failed to find matching data for ndi:%s\n",
- ifname));
- }
- } else if (ret == -ENODEV) {
- WL_INFORM(("Already deleted: %s\n", ifname));
- ret = BCME_OK;
- } else if (ret != BCME_OK) {
- WL_ERR(("failed to delete NDI[%d]\n", ret));
- }
- }
- } else {
- ret = -ENODEV;
- WL_ERR(("Bus is already down, no dev found to remove, ret = %d\n", ret));
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- /*
- * Return data peer from peer list
- * for peer_addr
- * NULL if not found
- */
- nan_ndp_peer_t *
- wl_cfgnan_data_get_peer(struct bcm_cfg80211 *cfg,
- struct ether_addr *peer_addr)
- {
- uint8 i;
- nan_ndp_peer_t* peer = cfg->nancfg.nan_ndp_peer_info;
- if (!peer) {
- WL_ERR(("wl_cfgnan_data_get_peer: nan_ndp_peer_info is NULL\n"));
- goto exit;
- }
- for (i = 0; i < cfg->nancfg.max_ndp_count; i++) {
- if (peer[i].peer_dp_state != NAN_PEER_DP_NOT_CONNECTED &&
- (!memcmp(peer_addr, &peer[i].peer_addr, ETHER_ADDR_LEN))) {
- return &peer[i];
- }
- }
- exit:
- return NULL;
- }
- /*
- * Returns True if
- * datapath exists for nan cfg
- * for any peer
- */
- bool
- wl_cfgnan_data_dp_exists(struct bcm_cfg80211 *cfg)
- {
- bool ret = FALSE;
- uint8 i;
- nan_ndp_peer_t* peer = NULL;
- if ((cfg->nan_init_state == FALSE) ||
- (cfg->nan_enable == FALSE)) {
- goto exit;
- }
- if (!cfg->nancfg.nan_ndp_peer_info) {
- goto exit;
- }
- peer = cfg->nancfg.nan_ndp_peer_info;
- for (i = 0; i < cfg->nancfg.max_ndp_count; i++) {
- if (peer[i].peer_dp_state != NAN_PEER_DP_NOT_CONNECTED) {
- ret = TRUE;
- break;
- }
- }
- exit:
- return ret;
- }
- /*
- * Returns True if
- * datapath exists for nan cfg
- * for given peer
- */
- bool
- wl_cfgnan_data_dp_exists_with_peer(struct bcm_cfg80211 *cfg,
- struct ether_addr *peer_addr)
- {
- bool ret = FALSE;
- nan_ndp_peer_t* peer = NULL;
- if ((cfg->nan_init_state == FALSE) ||
- (cfg->nan_enable == FALSE)) {
- goto exit;
- }
- /* check for peer exist */
- peer = wl_cfgnan_data_get_peer(cfg, peer_addr);
- if (peer) {
- ret = TRUE;
- }
- exit:
- return ret;
- }
- /*
- * As of now API only available
- * for setting state to CONNECTED
- * if applicable
- */
- void
- wl_cfgnan_data_set_peer_dp_state(struct bcm_cfg80211 *cfg,
- struct ether_addr *peer_addr, nan_peer_dp_state_t state)
- {
- nan_ndp_peer_t* peer = NULL;
- /* check for peer exist */
- peer = wl_cfgnan_data_get_peer(cfg, peer_addr);
- if (!peer) {
- goto end;
- }
- peer->peer_dp_state = state;
- end:
- return;
- }
- /* Adds peer to nan data peer list */
- void
- wl_cfgnan_data_add_peer(struct bcm_cfg80211 *cfg,
- struct ether_addr *peer_addr)
- {
- uint8 i;
- nan_ndp_peer_t* peer = NULL;
- /* check for peer exist */
- peer = wl_cfgnan_data_get_peer(cfg, peer_addr);
- if (peer) {
- peer->dp_count++;
- goto end;
- }
- peer = cfg->nancfg.nan_ndp_peer_info;
- for (i = 0; i < cfg->nancfg.max_ndp_count; i++) {
- if (peer[i].peer_dp_state == NAN_PEER_DP_NOT_CONNECTED) {
- break;
- }
- }
- if (i == NAN_MAX_NDP_PEER) {
- WL_DBG(("DP Peer list full, Droopping add peer req\n"));
- goto end;
- }
- /* Add peer to list */
- memcpy(&peer[i].peer_addr, peer_addr, ETHER_ADDR_LEN);
- peer[i].dp_count = 1;
- peer[i].peer_dp_state = NAN_PEER_DP_CONNECTING;
- end:
- return;
- }
- /* Removes nan data peer from peer list */
- void
- wl_cfgnan_data_remove_peer(struct bcm_cfg80211 *cfg,
- struct ether_addr *peer_addr)
- {
- nan_ndp_peer_t* peer = NULL;
- /* check for peer exist */
- peer = wl_cfgnan_data_get_peer(cfg, peer_addr);
- if (!peer) {
- WL_DBG(("DP Peer not present in list, "
- "Droopping remove peer req\n"));
- goto end;
- }
- peer->dp_count--;
- if (peer->dp_count == 0) {
- /* No more NDPs, delete entry */
- memset(peer, 0, sizeof(nan_ndp_peer_t));
- } else {
- /* Set peer dp state to connected if any ndp still exits */
- peer->peer_dp_state = NAN_PEER_DP_CONNECTED;
- }
- end:
- return;
- }
- int
- wl_cfgnan_data_path_request_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_datapath_cmd_data_t *cmd_data,
- uint8 *ndp_instance_id)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_buf_t *nan_buf = NULL;
- wl_nan_dp_req_t *datareq = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- uint16 buflen_avail;
- uint8 *pxtlv;
- struct wireless_dev *wdev;
- uint16 nan_buf_size;
- uint8 *resp_buf = NULL;
- /* Considering fixed params */
- uint16 data_size = WL_NAN_OBUF_DATA_OFFSET +
- OFFSETOF(wl_nan_dp_req_t, tlv_params);
- data_size = ALIGN_SIZE(data_size, 4);
- ret = wl_cfgnan_aligned_data_size_of_opt_dp_params(&data_size, cmd_data);
- if (unlikely(ret)) {
- WL_ERR(("Failed to get alligned size of optional params\n"));
- goto fail;
- }
- nan_buf_size = data_size;
- NAN_DBG_ENTER();
- mutex_lock(&cfg->if_sync);
- NAN_MUTEX_LOCK();
- #ifdef WL_IFACE_MGMT
- if ((ret = wl_cfg80211_handle_if_role_conflict(cfg, WL_IF_TYPE_NAN)) < 0) {
- WL_ERR(("Conflicting iface found to be active\n"));
- ret = BCME_UNSUPPORTED;
- goto fail;
- }
- #endif /* WL_IFACE_MGMT */
- #ifdef RTT_SUPPORT
- /* cancel any ongoing RTT session with peer
- * as we donot support DP and RNG to same peer
- */
- wl_cfgnan_clear_peer_ranging(cfg, &cmd_data->mac_addr,
- RTT_GEO_SUSPN_HOST_NDP_TRIGGER);
- #endif /* RTT_SUPPORT */
- nan_buf = MALLOCZ(cfg->osh, data_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- resp_buf = MALLOCZ(cfg->osh, data_size + NAN_IOVAR_NAME_SIZE);
- if (!resp_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data->avail_params, WL_AVAIL_LOCAL);
- if (unlikely(ret)) {
- WL_ERR(("Failed to set avail value with type local\n"));
- goto fail;
- }
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data->avail_params, WL_AVAIL_NDC);
- if (unlikely(ret)) {
- WL_ERR(("Failed to set avail value with type ndc\n"));
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(&nan_buf->cmds[0]);
- datareq = (wl_nan_dp_req_t *)(sub_cmd->data);
- /* setting default data path type to unicast */
- datareq->type = WL_NAN_DP_TYPE_UNICAST;
- if (cmd_data->pub_id) {
- datareq->pub_id = cmd_data->pub_id;
- }
- if (!ETHER_ISNULLADDR(&cmd_data->mac_addr.octet)) {
- ret = memcpy_s(&datareq->peer_mac, ETHER_ADDR_LEN,
- &cmd_data->mac_addr, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy ether addr provided\n"));
- goto fail;
- }
- } else {
- WL_ERR(("Invalid ether addr provided\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- /* Retrieve mac from given iface name */
- wdev = wl_cfg80211_get_wdev_from_ifname(cfg,
- (char *)cmd_data->ndp_iface);
- if (!wdev || ETHER_ISNULLADDR(wdev->netdev->dev_addr)) {
- ret = -EINVAL;
- WL_ERR(("Failed to retrieve wdev/dev addr for ndp_iface = %s\n",
- (char *)cmd_data->ndp_iface));
- goto fail;
- }
- if (!ETHER_ISNULLADDR(wdev->netdev->dev_addr)) {
- ret = memcpy_s(&datareq->ndi, ETHER_ADDR_LEN,
- wdev->netdev->dev_addr, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy ether addr provided\n"));
- goto fail;
- }
- WL_TRACE(("%s: Retrieved ndi mac " MACDBG "\n",
- __FUNCTION__, MAC2STRDBG(datareq->ndi.octet)));
- } else {
- WL_ERR(("Invalid NDI addr retrieved\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- datareq->ndl_qos.min_slots = NAN_NDL_QOS_MIN_SLOT_NO_PREF;
- datareq->ndl_qos.max_latency = NAN_NDL_QOS_MAX_LAT_NO_PREF;
- /* Fill the sub_command block */
- sub_cmd->id = htod16(WL_NAN_CMD_DATA_DATAREQ);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- OFFSETOF(wl_nan_dp_req_t, tlv_params);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- pxtlv = (uint8 *)&datareq->tlv_params;
- nan_buf_size -= (sub_cmd->len +
- OFFSETOF(bcm_iov_batch_subcmd_t, u.options));
- buflen_avail = nan_buf_size;
- if (cmd_data->svc_info.data && cmd_data->svc_info.dlen) {
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_SD_SVC_INFO, cmd_data->svc_info.dlen,
- cmd_data->svc_info.data,
- BCM_XTLV_OPTION_ALIGN32);
- if (ret != BCME_OK) {
- WL_ERR(("unable to process svc_spec_info: %d\n", ret));
- goto fail;
- }
- datareq->flags |= WL_NAN_DP_FLAG_SVC_INFO;
- }
- /* Security elements */
- if (cmd_data->csid) {
- WL_TRACE(("Cipher suite type is present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_CFG_SEC_CSID, sizeof(nan_sec_csid_e),
- (uint8*)&cmd_data->csid, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack on csid\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->ndp_cfg.security_cfg) {
- if ((cmd_data->key_type == NAN_SECURITY_KEY_INPUT_PMK) ||
- (cmd_data->key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE)) {
- if (cmd_data->key.data && cmd_data->key.dlen) {
- WL_TRACE(("optional pmk present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_CFG_SEC_PMK, cmd_data->key.dlen,
- cmd_data->key.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack on WL_NAN_XTLV_CFG_SEC_PMK\n",
- __FUNCTION__));
- goto fail;
- }
- }
- } else {
- WL_ERR(("Invalid security key type\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- if ((cmd_data->svc_hash.dlen == WL_NAN_SVC_HASH_LEN) &&
- (cmd_data->svc_hash.data)) {
- WL_TRACE(("svc hash present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_CFG_SVC_HASH, WL_NAN_SVC_HASH_LEN,
- cmd_data->svc_hash.data, BCM_XTLV_OPTION_ALIGN32);
- if (ret != BCME_OK) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_CFG_SVC_HASH\n",
- __FUNCTION__));
- goto fail;
- }
- } else {
- #ifdef WL_NAN_DISC_CACHE
- /* check in cache */
- nan_disc_result_cache *cache;
- cache = wl_cfgnan_get_disc_result(cfg,
- datareq->pub_id, &datareq->peer_mac);
- if (!cache) {
- ret = BCME_ERROR;
- WL_ERR(("invalid svc hash data or length = %d\n",
- cmd_data->svc_hash.dlen));
- goto fail;
- }
- WL_TRACE(("svc hash present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_CFG_SVC_HASH, WL_NAN_SVC_HASH_LEN,
- cache->svc_hash, BCM_XTLV_OPTION_ALIGN32);
- if (ret != BCME_OK) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_CFG_SVC_HASH\n",
- __FUNCTION__));
- goto fail;
- }
- #else
- ret = BCME_ERROR;
- WL_ERR(("invalid svc hash data or length = %d\n",
- cmd_data->svc_hash.dlen));
- goto fail;
- #endif /* WL_NAN_DISC_CACHE */
- }
- /* If the Data req is for secure data connection */
- datareq->flags |= WL_NAN_DP_FLAG_SECURITY;
- }
- sub_cmd->len += (buflen_avail - nan_buf_size);
- nan_buf->is_set = false;
- nan_buf->count++;
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, data_size,
- &(cmd_data->status), resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan data path request handler failed, ret = %d status %d\n",
- ret, cmd_data->status));
- goto fail;
- }
- /* check the response buff */
- if (ret == BCME_OK) {
- ret = process_resp_buf(resp_buf + WL_NAN_OBUF_DATA_OFFSET,
- ndp_instance_id, WL_NAN_CMD_DATA_DATAREQ);
- cmd_data->ndp_instance_id = *ndp_instance_id;
- }
- WL_INFORM_MEM(("[NAN] DP request successfull (ndp_id:%d)\n",
- cmd_data->ndp_instance_id));
- /* Add peer to data ndp peer list */
- wl_cfgnan_data_add_peer(cfg, &datareq->peer_mac);
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, data_size);
- }
- if (resp_buf) {
- MFREE(cfg->osh, resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- }
- NAN_MUTEX_UNLOCK();
- mutex_unlock(&cfg->if_sync);
- NAN_DBG_EXIT();
- return ret;
- }
- int
- wl_cfgnan_data_path_response_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_datapath_cmd_data_t *cmd_data)
- {
- s32 ret = BCME_OK;
- bcm_iov_batch_buf_t *nan_buf = NULL;
- wl_nan_dp_resp_t *dataresp = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- uint16 buflen_avail;
- uint8 *pxtlv;
- struct wireless_dev *wdev;
- uint16 nan_buf_size;
- uint8 *resp_buf = NULL;
- /* Considering fixed params */
- uint16 data_size = WL_NAN_OBUF_DATA_OFFSET +
- OFFSETOF(wl_nan_dp_resp_t, tlv_params);
- data_size = ALIGN_SIZE(data_size, 4);
- ret = wl_cfgnan_aligned_data_size_of_opt_dp_params(&data_size, cmd_data);
- if (unlikely(ret)) {
- WL_ERR(("Failed to get alligned size of optional params\n"));
- goto fail;
- }
- nan_buf_size = data_size;
- NAN_DBG_ENTER();
- mutex_lock(&cfg->if_sync);
- NAN_MUTEX_LOCK();
- #ifdef WL_IFACE_MGMT
- if ((ret = wl_cfg80211_handle_if_role_conflict(cfg, WL_IF_TYPE_NAN)) < 0) {
- WL_ERR(("Conflicting iface found to be active\n"));
- ret = BCME_UNSUPPORTED;
- goto fail;
- }
- #endif /* WL_IFACE_MGMT */
- nan_buf = MALLOCZ(cfg->osh, data_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- resp_buf = MALLOCZ(cfg->osh, data_size + NAN_IOVAR_NAME_SIZE);
- if (!resp_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data->avail_params, WL_AVAIL_LOCAL);
- if (unlikely(ret)) {
- WL_ERR(("Failed to set avail value with type local\n"));
- goto fail;
- }
- ret = wl_cfgnan_set_nan_avail(bcmcfg_to_prmry_ndev(cfg),
- cfg, &cmd_data->avail_params, WL_AVAIL_NDC);
- if (unlikely(ret)) {
- WL_ERR(("Failed to set avail value with type ndc\n"));
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(&nan_buf->cmds[0]);
- dataresp = (wl_nan_dp_resp_t *)(sub_cmd->data);
- /* Setting default data path type to unicast */
- dataresp->type = WL_NAN_DP_TYPE_UNICAST;
- /* Changing status value as per fw convention */
- dataresp->status = cmd_data->rsp_code ^= 1;
- dataresp->reason_code = 0;
- /* ndp instance id must be from 1 to 255, 0 is reserved */
- if (cmd_data->ndp_instance_id < NAN_ID_MIN ||
- cmd_data->ndp_instance_id > NAN_ID_MAX) {
- WL_ERR(("Invalid ndp instance id: %d\n", cmd_data->ndp_instance_id));
- ret = BCME_BADARG;
- goto fail;
- }
- dataresp->ndp_id = cmd_data->ndp_instance_id;
- /* Retrieved initiator ndi from NanDataPathRequestInd */
- if (!ETHER_ISNULLADDR(&cfg->initiator_ndi.octet)) {
- ret = memcpy_s(&dataresp->mac_addr, ETHER_ADDR_LEN,
- &cfg->initiator_ndi, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy initiator ndi\n"));
- goto fail;
- }
- } else {
- WL_ERR(("Invalid ether addr retrieved\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- /* Interface is not mandatory, when it is a reject from framework */
- if (dataresp->status != WL_NAN_DP_STATUS_REJECTED) {
- /* Retrieve mac from given iface name */
- wdev = wl_cfg80211_get_wdev_from_ifname(cfg,
- (char *)cmd_data->ndp_iface);
- if (!wdev || ETHER_ISNULLADDR(wdev->netdev->dev_addr)) {
- ret = -EINVAL;
- WL_ERR(("Failed to retrieve wdev/dev addr for ndp_iface = %s\n",
- (char *)cmd_data->ndp_iface));
- goto fail;
- }
- if (!ETHER_ISNULLADDR(wdev->netdev->dev_addr)) {
- ret = memcpy_s(&dataresp->ndi, ETHER_ADDR_LEN,
- wdev->netdev->dev_addr, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy responder ndi\n"));
- goto fail;
- }
- WL_TRACE(("%s: Retrieved ndi mac " MACDBG "\n",
- __FUNCTION__, MAC2STRDBG(dataresp->ndi.octet)));
- } else {
- WL_ERR(("Invalid NDI addr retrieved\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- }
- dataresp->ndl_qos.min_slots = NAN_NDL_QOS_MIN_SLOT_NO_PREF;
- dataresp->ndl_qos.max_latency = NAN_NDL_QOS_MAX_LAT_NO_PREF;
- /* Fill the sub_command block */
- sub_cmd->id = htod16(WL_NAN_CMD_DATA_DATARESP);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- OFFSETOF(wl_nan_dp_resp_t, tlv_params);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- pxtlv = (uint8 *)&dataresp->tlv_params;
- nan_buf_size -= (sub_cmd->len +
- OFFSETOF(bcm_iov_batch_subcmd_t, u.options));
- buflen_avail = nan_buf_size;
- if (cmd_data->svc_info.data && cmd_data->svc_info.dlen) {
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_SD_SVC_INFO, cmd_data->svc_info.dlen,
- cmd_data->svc_info.data,
- BCM_XTLV_OPTION_ALIGN32);
- if (ret != BCME_OK) {
- WL_ERR(("unable to process svc_spec_info: %d\n", ret));
- goto fail;
- }
- dataresp->flags |= WL_NAN_DP_FLAG_SVC_INFO;
- }
- /* Security elements */
- if (cmd_data->csid) {
- WL_TRACE(("Cipher suite type is present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_CFG_SEC_CSID, sizeof(nan_sec_csid_e),
- (uint8*)&cmd_data->csid, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack csid\n", __FUNCTION__));
- goto fail;
- }
- }
- if (cmd_data->ndp_cfg.security_cfg) {
- if ((cmd_data->key_type == NAN_SECURITY_KEY_INPUT_PMK) ||
- (cmd_data->key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE)) {
- if (cmd_data->key.data && cmd_data->key.dlen) {
- WL_TRACE(("optional pmk present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_CFG_SEC_PMK, cmd_data->key.dlen,
- cmd_data->key.data, BCM_XTLV_OPTION_ALIGN32);
- if (unlikely(ret)) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_CFG_SEC_PMK\n",
- __FUNCTION__));
- goto fail;
- }
- }
- } else {
- WL_ERR(("Invalid security key type\n"));
- ret = BCME_BADARG;
- goto fail;
- }
- if ((cmd_data->svc_hash.dlen == WL_NAN_SVC_HASH_LEN) &&
- (cmd_data->svc_hash.data)) {
- WL_TRACE(("svc hash present, pack it\n"));
- ret = bcm_pack_xtlv_entry(&pxtlv, &nan_buf_size,
- WL_NAN_XTLV_CFG_SVC_HASH, WL_NAN_SVC_HASH_LEN,
- cmd_data->svc_hash.data,
- BCM_XTLV_OPTION_ALIGN32);
- if (ret != BCME_OK) {
- WL_ERR(("%s: fail to pack WL_NAN_XTLV_CFG_SVC_HASH\n",
- __FUNCTION__));
- goto fail;
- }
- }
- /* If the Data resp is for secure data connection */
- dataresp->flags |= WL_NAN_DP_FLAG_SECURITY;
- }
- sub_cmd->len += (buflen_avail - nan_buf_size);
- nan_buf->is_set = false;
- nan_buf->count++;
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, data_size,
- &(cmd_data->status), resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan data path response handler failed, error = %d, status %d\n",
- ret, cmd_data->status));
- goto fail;
- }
- WL_INFORM_MEM(("[NAN] DP response successfull (ndp_id:%d)\n", dataresp->ndp_id));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, data_size);
- }
- if (resp_buf) {
- MFREE(cfg->osh, resp_buf, data_size + NAN_IOVAR_NAME_SIZE);
- }
- NAN_MUTEX_UNLOCK();
- mutex_unlock(&cfg->if_sync);
- NAN_DBG_EXIT();
- return ret;
- }
- int wl_cfgnan_data_path_end_handler(struct net_device *ndev,
- struct bcm_cfg80211 *cfg, nan_datapath_cmd_data_t *cmd_data)
- {
- bcm_iov_batch_buf_t *nan_buf = NULL;
- wl_nan_dp_end_t *dataend = NULL;
- bcm_iov_batch_subcmd_t *sub_cmd = NULL;
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- dhd_pub_t *dhdp = wl_cfg80211_get_dhdp(ndev);
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- if (!dhdp->up) {
- WL_ERR(("bus is already down, hence blocking nan dp end\n"));
- ret = BCME_OK;
- goto fail;
- }
- if (!cfg->nan_enable) {
- WL_ERR(("nan is not enabled, nan dp end blocked\n"));
- ret = BCME_OK;
- goto fail;
- }
- /* ndp instance id must be from 1 to 255, 0 is reserved */
- if (cmd_data->ndp_instance_id < NAN_ID_MIN ||
- cmd_data->ndp_instance_id > NAN_ID_MAX) {
- WL_ERR(("Invalid ndp instance id: %d\n", cmd_data->ndp_instance_id));
- ret = BCME_BADARG;
- goto fail;
- }
- nan_buf = MALLOCZ(cfg->osh, nan_buf_size);
- if (!nan_buf) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- ret = BCME_NOMEM;
- goto fail;
- }
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t*)(&nan_buf->cmds[0]);
- dataend = (wl_nan_dp_end_t *)(sub_cmd->data);
- /* Fill sub_cmd block */
- sub_cmd->id = htod16(WL_NAN_CMD_DATA_DATAEND);
- sub_cmd->len = sizeof(sub_cmd->u.options) +
- sizeof(*dataend);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- dataend->lndp_id = cmd_data->ndp_instance_id;
- /*
- * Currently fw requires ndp_id and reason to end the data path
- * But wifi_nan.h takes ndp_instances_count and ndp_id.
- * Will keep reason = accept always.
- */
- dataend->status = 1;
- nan_buf->is_set = true;
- nan_buf->count++;
- nan_buf_size -= (sub_cmd->len +
- OFFSETOF(bcm_iov_batch_subcmd_t, u.options));
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(ndev, cfg, nan_buf, nan_buf_size,
- &(cmd_data->status),
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(cmd_data->status)) {
- WL_ERR(("nan data path end handler failed, error = %d status %d\n",
- ret, cmd_data->status));
- goto fail;
- }
- WL_INFORM_MEM(("[NAN] DP end successfull (ndp_id:%d)\n",
- dataend->lndp_id));
- fail:
- if (nan_buf) {
- MFREE(cfg->osh, nan_buf, NAN_IOCTL_BUF_SIZE);
- }
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- #ifdef WL_NAN_DISC_CACHE
- int wl_cfgnan_sec_info_handler(struct bcm_cfg80211 *cfg,
- nan_datapath_sec_info_cmd_data_t *cmd_data, nan_hal_resp_t *nan_req_resp)
- {
- s32 ret = BCME_NOTFOUND;
- /* check in cache */
- nan_disc_result_cache *disc_cache = NULL;
- nan_svc_info_t *svc_info = NULL;
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- if (!cfg->nan_init_state) {
- WL_ERR(("nan is not initialized/nmi doesnt exists\n"));
- ret = BCME_NOTENABLED;
- goto fail;
- }
- /* datapath request context */
- if (cmd_data->pub_id && !ETHER_ISNULLADDR(&cmd_data->mac_addr)) {
- disc_cache = wl_cfgnan_get_disc_result(cfg,
- cmd_data->pub_id, &cmd_data->mac_addr);
- WL_DBG(("datapath request: PUB ID: = %d\n",
- cmd_data->pub_id));
- if (disc_cache) {
- (void)memcpy_s(nan_req_resp->svc_hash, WL_NAN_SVC_HASH_LEN,
- disc_cache->svc_hash, WL_NAN_SVC_HASH_LEN);
- ret = BCME_OK;
- } else {
- WL_ERR(("disc_cache is NULL\n"));
- goto fail;
- }
- }
- /* datapath response context */
- if (cmd_data->ndp_instance_id) {
- WL_DBG(("datapath response: NDP ID: = %d\n",
- cmd_data->ndp_instance_id));
- svc_info = wl_cfgnan_get_svc_inst(cfg, 0, cmd_data->ndp_instance_id);
- /* Note: svc_info will not be present in OOB cases
- * In such case send NMI alone and let HAL handle if
- * svc_hash is mandatory
- */
- if (svc_info) {
- WL_DBG(("svc hash present, pack it\n"));
- (void)memcpy_s(nan_req_resp->svc_hash, WL_NAN_SVC_HASH_LEN,
- svc_info->svc_hash, WL_NAN_SVC_HASH_LEN);
- } else {
- WL_INFORM_MEM(("svc_info not present..assuming OOB DP\n"));
- }
- /* Always send NMI */
- (void)memcpy_s(nan_req_resp->pub_nmi, ETHER_ADDR_LEN,
- cfg->nan_nmi_mac, ETHER_ADDR_LEN);
- ret = BCME_OK;
- }
- fail:
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- static s32 wl_nan_cache_to_event_data(nan_disc_result_cache *cache,
- nan_event_data_t *nan_event_data, osl_t *osh)
- {
- s32 ret = BCME_OK;
- NAN_DBG_ENTER();
- nan_event_data->pub_id = cache->pub_id;
- nan_event_data->sub_id = cache->sub_id;
- nan_event_data->publish_rssi = cache->publish_rssi;
- nan_event_data->peer_cipher_suite = cache->peer_cipher_suite;
- ret = memcpy_s(&nan_event_data->remote_nmi, ETHER_ADDR_LEN,
- &cache->peer, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy cached peer nan nmi\n"));
- goto fail;
- }
- if (cache->svc_info.dlen && cache->svc_info.data) {
- nan_event_data->svc_info.dlen = cache->svc_info.dlen;
- nan_event_data->svc_info.data =
- MALLOCZ(osh, nan_event_data->svc_info.dlen);
- if (!nan_event_data->svc_info.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- nan_event_data->svc_info.dlen = 0;
- ret = -ENOMEM;
- goto fail;
- }
- ret = memcpy_s(nan_event_data->svc_info.data, nan_event_data->svc_info.dlen,
- cache->svc_info.data, cache->svc_info.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy cached svc info data\n"));
- goto fail;
- }
- }
- if (cache->tx_match_filter.dlen && cache->tx_match_filter.data) {
- nan_event_data->tx_match_filter.dlen = cache->tx_match_filter.dlen;
- nan_event_data->tx_match_filter.data =
- MALLOCZ(osh, nan_event_data->tx_match_filter.dlen);
- if (!nan_event_data->tx_match_filter.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- nan_event_data->tx_match_filter.dlen = 0;
- ret = -ENOMEM;
- goto fail;
- }
- ret = memcpy_s(nan_event_data->tx_match_filter.data,
- nan_event_data->tx_match_filter.dlen,
- cache->tx_match_filter.data, cache->tx_match_filter.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy cached tx match filter data\n"));
- goto fail;
- }
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- #endif /* WL_NAN_DISC_CACHE */
- /* API to cancel the ranging with peer
- * For geofence initiator, suspend ranging.
- * for directed RTT initiator , report fail result, cancel ranging
- * and clear ranging instance
- * For responder, cancel ranging and clear ranging instance
- */
- #ifdef RTT_SUPPORT
- static s32
- wl_cfgnan_clear_peer_ranging(struct bcm_cfg80211 *cfg,
- struct ether_addr *peer, int reason)
- {
- uint32 status = 0;
- nan_ranging_inst_t *rng_inst = NULL;
- int err = BCME_OK;
- struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
- dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
- rng_inst = wl_cfgnan_check_for_ranging(cfg, peer);
- if (rng_inst) {
- if (rng_inst->range_type == RTT_TYPE_NAN_GEOFENCE) {
- err = wl_cfgnan_suspend_geofence_rng_session(ndev,
- peer, reason, 0);
- } else {
- if (rng_inst->range_type == RTT_TYPE_NAN_DIRECTED) {
- dhd_rtt_handle_nan_rtt_session_end(dhdp,
- peer);
- }
- /* responder */
- err = wl_cfgnan_cancel_ranging(ndev, cfg,
- rng_inst->range_id,
- NAN_RNG_TERM_FLAG_IMMEDIATE, &status);
- bzero(rng_inst, sizeof(*rng_inst));
- }
- }
- if (err) {
- WL_ERR(("Failed to stop ranging with peer %d\n", err));
- }
- return err;
- }
- #endif /* RTT_SUPPORT */
- static s32
- wl_nan_dp_cmn_event_data(struct bcm_cfg80211 *cfg, void *event_data,
- uint16 data_len, uint16 *tlvs_offset,
- uint16 *nan_opts_len, uint32 event_num,
- int *hal_event_id, nan_event_data_t *nan_event_data)
- {
- s32 ret = BCME_OK;
- uint8 i;
- wl_nan_ev_datapath_cmn_t *ev_dp;
- nan_svc_info_t *svc_info;
- bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
- #ifdef RTT_SUPPORT
- nan_ranging_inst_t *rng_inst = NULL;
- #endif /* RTT_SUPPORT */
- if (xtlv->id == WL_NAN_XTLV_DATA_DP_INFO) {
- ev_dp = (wl_nan_ev_datapath_cmn_t *)xtlv->data;
- NAN_DBG_ENTER();
- BCM_REFERENCE(svc_info);
- BCM_REFERENCE(i);
- /* Mapping to common struct between DHD and HAL */
- WL_TRACE(("Event type: %d\n", ev_dp->type));
- nan_event_data->type = ev_dp->type;
- WL_TRACE(("pub_id: %d\n", ev_dp->pub_id));
- nan_event_data->pub_id = ev_dp->pub_id;
- WL_TRACE(("security: %d\n", ev_dp->security));
- nan_event_data->security = ev_dp->security;
- /* Store initiator_ndi, required for data_path_response_request */
- ret = memcpy_s(&cfg->initiator_ndi, ETHER_ADDR_LEN,
- &ev_dp->initiator_ndi, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy event's initiator addr\n"));
- goto fail;
- }
- if (ev_dp->type == NAN_DP_SESSION_UNICAST) {
- WL_INFORM_MEM(("NDP ID: %d\n", ev_dp->ndp_id));
- nan_event_data->ndp_id = ev_dp->ndp_id;
- WL_TRACE(("INITIATOR_NDI: " MACDBG "\n",
- MAC2STRDBG(ev_dp->initiator_ndi.octet)));
- WL_TRACE(("RESPONDOR_NDI: " MACDBG "\n",
- MAC2STRDBG(ev_dp->responder_ndi.octet)));
- WL_TRACE(("PEER NMI: " MACDBG "\n",
- MAC2STRDBG(ev_dp->peer_nmi.octet)));
- ret = memcpy_s(&nan_event_data->remote_nmi, ETHER_ADDR_LEN,
- &ev_dp->peer_nmi, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy event's peer nmi\n"));
- goto fail;
- }
- } else {
- /* type is multicast */
- WL_INFORM_MEM(("NDP ID: %d\n", ev_dp->mc_id));
- nan_event_data->ndp_id = ev_dp->mc_id;
- WL_TRACE(("PEER NMI: " MACDBG "\n",
- MAC2STRDBG(ev_dp->peer_nmi.octet)));
- ret = memcpy_s(&nan_event_data->remote_nmi, ETHER_ADDR_LEN,
- &ev_dp->peer_nmi,
- ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy event's peer nmi\n"));
- goto fail;
- }
- }
- *tlvs_offset = OFFSETOF(wl_nan_ev_datapath_cmn_t, opt_tlvs) +
- OFFSETOF(bcm_xtlv_t, data);
- *nan_opts_len = data_len - *tlvs_offset;
- if (event_num == WL_NAN_EVENT_PEER_DATAPATH_IND) {
- *hal_event_id = GOOGLE_NAN_EVENT_DATA_REQUEST;
- #ifdef WL_NAN_DISC_CACHE
- svc_info = wl_cfgnan_get_svc_inst(cfg, nan_event_data->pub_id, 0);
- if (svc_info) {
- for (i = 0; i < NAN_MAX_SVC_INST; i++) {
- if (!svc_info->ndp_id[i]) {
- WL_TRACE(("Found empty field\n"));
- break;
- }
- }
- if (i == NAN_MAX_SVC_INST) {
- WL_ERR(("%s:cannot accommadate ndp id\n", __FUNCTION__));
- ret = BCME_NORESOURCE;
- goto fail;
- }
- svc_info->ndp_id[i] = nan_event_data->ndp_id;
- /* Add peer to data ndp peer list */
- wl_cfgnan_data_add_peer(cfg, &ev_dp->peer_nmi);
- #ifdef RTT_SUPPORT
- /* cancel any ongoing RTT session with peer
- * as we donot support DP and RNG to same peer
- */
- wl_cfgnan_clear_peer_ranging(cfg, &ev_dp->peer_nmi,
- RTT_GEO_SUSPN_PEER_NDP_TRIGGER);
- #endif /* RTT_SUPPORT */
- ret = BCME_OK;
- }
- #endif /* WL_NAN_DISC_CACHE */
- } else if (event_num == WL_NAN_EVENT_DATAPATH_ESTB) {
- *hal_event_id = GOOGLE_NAN_EVENT_DATA_CONFIRMATION;
- if (ev_dp->role == NAN_DP_ROLE_INITIATOR) {
- ret = memcpy_s(&nan_event_data->responder_ndi, ETHER_ADDR_LEN,
- &ev_dp->responder_ndi,
- ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy event's responder ndi\n"));
- goto fail;
- }
- WL_TRACE(("REMOTE_NDI: " MACDBG "\n",
- MAC2STRDBG(ev_dp->responder_ndi.octet)));
- WL_TRACE(("Initiator status %d\n", nan_event_data->status));
- } else {
- ret = memcpy_s(&nan_event_data->responder_ndi, ETHER_ADDR_LEN,
- &ev_dp->initiator_ndi,
- ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy event's responder ndi\n"));
- goto fail;
- }
- WL_TRACE(("REMOTE_NDI: " MACDBG "\n",
- MAC2STRDBG(ev_dp->initiator_ndi.octet)));
- }
- if (ev_dp->status == NAN_NDP_STATUS_ACCEPT) {
- nan_event_data->status = NAN_DP_REQUEST_ACCEPT;
- wl_cfgnan_data_set_peer_dp_state(cfg, &ev_dp->peer_nmi,
- NAN_PEER_DP_CONNECTED);
- } else if (ev_dp->status == NAN_NDP_STATUS_REJECT) {
- nan_event_data->status = NAN_DP_REQUEST_REJECT;
- /* Remove peer from data ndp peer list */
- wl_cfgnan_data_remove_peer(cfg, &ev_dp->peer_nmi);
- #ifdef RTT_SUPPORT
- rng_inst = wl_cfgnan_check_for_ranging(cfg, &ev_dp->peer_nmi);
- if (rng_inst) {
- /* Trigger/Reset geofence RTT */
- wl_cfgnan_reset_geofence_ranging(cfg,
- rng_inst, RTT_SCHED_DP_REJECTED);
- }
- #endif /* RTT_SUPPORT */
- } else {
- WL_ERR(("%s:Status code = %x not expected\n",
- __FUNCTION__, ev_dp->status));
- ret = BCME_ERROR;
- goto fail;
- }
- WL_TRACE(("Responder status %d\n", nan_event_data->status));
- wl_cfgnan_update_dp_mask(cfg, true, nan_event_data->ndp_id);
- } else if (event_num == WL_NAN_EVENT_DATAPATH_END) {
- /* Mapping to common struct between DHD and HAL */
- *hal_event_id = GOOGLE_NAN_EVENT_DATA_END;
- wl_cfgnan_update_dp_mask(cfg, false, nan_event_data->ndp_id);
- #ifdef WL_NAN_DISC_CACHE
- if (ev_dp->role != NAN_DP_ROLE_INITIATOR) {
- /* Only at Responder side,
- * If dp is ended,
- * clear the resp ndp id from the svc info cache
- */
- svc_info = wl_cfgnan_get_svc_inst(cfg, 0, nan_event_data->ndp_id);
- if (svc_info) {
- for (i = 0; i < NAN_MAX_SVC_INST; i++) {
- if (svc_info->ndp_id[i] == nan_event_data->ndp_id) {
- svc_info->ndp_id[i] = 0;
- }
- }
- } else {
- WL_DBG(("couldn't find entry for ndp id = %d\n",
- nan_event_data->ndp_id));
- }
- }
- #endif /* WL_NAN_DISC_CACHE */
- /* Remove peer from data ndp peer list */
- wl_cfgnan_data_remove_peer(cfg, &ev_dp->peer_nmi);
- #ifdef RTT_SUPPORT
- WL_INFORM_MEM(("DP_END for REMOTE_NMI: " MACDBG "\n",
- MAC2STRDBG(&ev_dp->peer_nmi)));
- rng_inst = wl_cfgnan_check_for_ranging(cfg, &ev_dp->peer_nmi);
- if (rng_inst) {
- /* Trigger/Reset geofence RTT */
- WL_INFORM_MEM(("sched geofence rtt from DP_END ctx: " MACDBG "\n",
- MAC2STRDBG(&rng_inst->peer_addr)));
- wl_cfgnan_reset_geofence_ranging(cfg, rng_inst,
- RTT_SCHED_DP_END);
- }
- #endif /* RTT_SUPPORT */
- }
- } else {
- /* Follow though, not handling other IDs as of now */
- WL_DBG(("%s:ID = 0x%02x not supported\n", __FUNCTION__, xtlv->id));
- }
- fail:
- NAN_DBG_EXIT();
- return ret;
- }
- #define IN_GEOFENCE(ingress, egress, distance) (((distance) <= (ingress)) && \
- ((distance) >= (egress)))
- #define IS_INGRESS_VAL(ingress, distance) ((distance) < (ingress))
- #define IS_EGRESS_VAL(egress, distance) ((distance) > (egress))
- static bool
- wl_cfgnan_check_ranging_cond(nan_svc_info_t *svc_info, uint32 distance,
- uint8 *ranging_ind, uint32 prev_distance)
- {
- uint8 svc_ind = svc_info->ranging_ind;
- bool notify = FALSE;
- bool range_rep_ev_once =
- !!(svc_info->svc_range_status & SVC_RANGE_REP_EVENT_ONCE);
- uint32 ingress_limit = svc_info->ingress_limit;
- uint32 egress_limit = svc_info->egress_limit;
- WL_DBG(("wl_cfgnan_check_ranging_cond: Checking the svc ranging cnd %d"
- " distance %d prev_distance %d, range_rep_ev_once %d\n",
- svc_ind, distance, prev_distance, range_rep_ev_once));
- WL_DBG(("wl_cfgnan_check_ranging_cond: Checking the SVC ingress and"
- " egress limits %d %d\n", ingress_limit, egress_limit));
- if (svc_ind & NAN_RANGE_INDICATION_CONT) {
- *ranging_ind = NAN_RANGE_INDICATION_CONT;
- notify = TRUE;
- WL_ERR(("\n%s :Svc has continous Ind %d\n",
- __FUNCTION__, __LINE__));
- goto done;
- }
- if (svc_ind == (NAN_RANGE_INDICATION_INGRESS |
- NAN_RANGE_INDICATION_EGRESS)) {
- if (IN_GEOFENCE(ingress_limit, egress_limit, distance)) {
- /* if not already in geofence */
- if ((range_rep_ev_once == FALSE) ||
- (!IN_GEOFENCE(ingress_limit, egress_limit,
- prev_distance))) {
- notify = TRUE;
- if (distance < ingress_limit) {
- *ranging_ind = NAN_RANGE_INDICATION_INGRESS;
- } else {
- *ranging_ind = NAN_RANGE_INDICATION_EGRESS;
- }
- WL_ERR(("\n%s :Svc has geofence Ind %d res_ind %d\n",
- __FUNCTION__, __LINE__, *ranging_ind));
- }
- }
- goto done;
- }
- if (svc_ind == NAN_RANGE_INDICATION_INGRESS) {
- if (IS_INGRESS_VAL(ingress_limit, distance)) {
- if ((range_rep_ev_once == FALSE) ||
- (prev_distance == INVALID_DISTANCE) ||
- !IS_INGRESS_VAL(ingress_limit, prev_distance)) {
- notify = TRUE;
- *ranging_ind = NAN_RANGE_INDICATION_INGRESS;
- WL_ERR(("\n%s :Svc has ingress Ind %d\n",
- __FUNCTION__, __LINE__));
- }
- }
- goto done;
- }
- if (svc_ind == NAN_RANGE_INDICATION_EGRESS) {
- if (IS_EGRESS_VAL(egress_limit, distance)) {
- if ((range_rep_ev_once == FALSE) ||
- (prev_distance == INVALID_DISTANCE) ||
- !IS_EGRESS_VAL(egress_limit, prev_distance)) {
- notify = TRUE;
- *ranging_ind = NAN_RANGE_INDICATION_EGRESS;
- WL_ERR(("\n%s :Svc has egress Ind %d\n",
- __FUNCTION__, __LINE__));
- }
- }
- goto done;
- }
- done:
- svc_info->svc_range_status |= SVC_RANGE_REP_EVENT_ONCE;
- return notify;
- }
- static int
- wl_cfgnan_event_disc_result(struct bcm_cfg80211 *cfg,
- nan_event_data_t *nan_event_data)
- {
- int ret = BCME_OK;
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
- ret = wl_cfgvendor_send_nan_event(cfg->wdev->wiphy, bcmcfg_to_prmry_ndev(cfg),
- GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH, nan_event_data);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to send event to nan hal\n"));
- }
- #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
- return ret;
- }
- static int32
- wl_cfgnan_notify_disc_with_ranging(struct bcm_cfg80211 *cfg,
- nan_ranging_inst_t *rng_inst, nan_event_data_t *nan_event_data, uint32 distance)
- {
- nan_svc_info_t *svc_info;
- bool notify_svc = FALSE;
- nan_disc_result_cache *disc_res = cfg->nan_disc_cache;
- uint8 ranging_ind = 0;
- int ret = BCME_OK;
- int i = 0, j = 0;
- for (i = 0; i < MAX_SUBSCRIBES; i++) {
- svc_info = rng_inst->svc_idx[i];
- if (svc_info) {
- if (nan_event_data->ranging_result_present) {
- notify_svc = wl_cfgnan_check_ranging_cond(svc_info, distance,
- &ranging_ind, rng_inst->prev_distance_mm);
- nan_event_data->ranging_ind = ranging_ind;
- } else {
- /* Report only if ranging was needed */
- notify_svc = svc_info->ranging_required;
- }
- WL_DBG(("wl_cfgnan_notify_disc_with_ranging: Ranging notify for"
- " svc_id %d, notify %d and ind %d\n",
- svc_info->svc_id, notify_svc, ranging_ind));
- } else {
- continue;
- }
- if (notify_svc) {
- for (j = 0; j < NAN_MAX_CACHE_DISC_RESULT; j++) {
- if (!memcmp(&disc_res[j].peer,
- &(rng_inst->peer_addr), ETHER_ADDR_LEN) &&
- (svc_info->svc_id == disc_res[j].sub_id)) {
- ret = wl_nan_cache_to_event_data(&disc_res[j],
- nan_event_data, cfg->osh);
- ret = wl_cfgnan_event_disc_result(cfg, nan_event_data);
- /* If its not match once, clear it as the FW indicates
- * again.
- */
- if (!(svc_info->flags & WL_NAN_MATCH_ONCE)) {
- wl_cfgnan_remove_disc_result(cfg, svc_info->svc_id);
- }
- }
- }
- }
- }
- WL_DBG(("notify_disc_with_ranging done ret %d\n", ret));
- return ret;
- }
- #ifdef RTT_SUPPORT
- static int32
- wl_cfgnan_handle_directed_rtt_report(struct bcm_cfg80211 *cfg,
- nan_ranging_inst_t *rng_inst, uint8 rng_id)
- {
- int ret = BCME_OK;
- uint32 status;
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- ret = wl_cfgnan_cancel_ranging(bcmcfg_to_prmry_ndev(cfg), cfg,
- rng_id, NAN_RNG_TERM_FLAG_IMMEDIATE, &status);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("%s:nan range cancel failed ret = %d status = %d\n",
- __FUNCTION__, ret, status));
- }
- dhd_rtt_handle_nan_rtt_session_end(dhd, &rng_inst->peer_addr);
- wl_cfgnan_reset_geofence_ranging(cfg, rng_inst, RTT_SCHED_RNG_RPT_DIRECTED);
- WL_DBG(("Ongoing ranging session is cancelled \n"));
- return ret;
- }
- #endif /* RTT_SUPPORT */
- static void
- wl_cfgnan_disc_result_on_geofence_cancel(struct bcm_cfg80211 *cfg,
- nan_ranging_inst_t *rng_inst)
- {
- nan_event_data_t *nan_event_data = NULL;
- nan_event_data = MALLOCZ(cfg->osh, sizeof(*nan_event_data));
- if (!nan_event_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- goto exit;
- }
- wl_cfgnan_notify_disc_with_ranging(cfg, rng_inst, nan_event_data, 0);
- exit:
- wl_cfgnan_clear_nan_event_data(cfg, nan_event_data);
- return;
- }
- #ifdef RTT_SUPPORT
- void
- wl_cfgnan_process_range_report(struct bcm_cfg80211 *cfg,
- wl_nan_ev_rng_rpt_ind_t *range_res)
- {
- nan_ranging_inst_t *rng_inst = NULL;
- nan_event_data_t nan_event_data;
- UNUSED_PARAMETER(nan_event_data);
- rng_inst = wl_cfgnan_check_for_ranging(cfg, &range_res->peer_m_addr);
- if (!rng_inst) {
- WL_ERR(("wl_cfgnan_process_range_report: No ranging instance "
- "but received RNG RPT event..check \n"));
- goto exit;
- }
- #ifdef NAN_RTT_DBG
- DUMP_NAN_RTT_INST(rng_inst);
- DUMP_NAN_RTT_RPT(range_res);
- #endif // endif
- range_res->rng_id = rng_inst->range_id;
- bzero(&nan_event_data, sizeof(nan_event_data));
- nan_event_data.ranging_result_present = 1;
- nan_event_data.range_measurement_cm = range_res->dist_mm;
- (void)memcpy_s(&nan_event_data.remote_nmi, ETHER_ADDR_LEN,
- &range_res->peer_m_addr, ETHER_ADDR_LEN);
- nan_event_data.ranging_ind = range_res->indication;
- if (rng_inst->range_type == RTT_TYPE_NAN_GEOFENCE) {
- /* check in cache and event match to host */
- wl_cfgnan_notify_disc_with_ranging(cfg, rng_inst, &nan_event_data,
- range_res->dist_mm);
- rng_inst->prev_distance_mm = range_res->dist_mm;
- }
- if (rng_inst->range_type == RTT_TYPE_NAN_DIRECTED) {
- wl_cfgnan_handle_directed_rtt_report(cfg, rng_inst, range_res->rng_id);
- }
- exit:
- return;
- }
- #endif /* RTT_SUPPORT */
- static void
- wl_nan_print_status(wl_nan_conf_status_t *nstatus)
- {
- printf("> enabled: %d\n", nstatus->enabled);
- printf("> Current NMI: " MACDBG "\n", MAC2STRDBG(nstatus->nmi.octet));
- printf("> Current cluster_id: " MACDBG "\n", MAC2STRDBG(nstatus->cid.octet));
- switch (nstatus->role) {
- case WL_NAN_ROLE_AUTO:
- printf("> role: %s (%d)\n", "auto", nstatus->role);
- break;
- case WL_NAN_ROLE_NON_MASTER_NON_SYNC:
- printf("> role: %s (%d)\n", "non-master-non-sync", nstatus->role);
- break;
- case WL_NAN_ROLE_NON_MASTER_SYNC:
- printf("> role: %s (%d)\n", "non-master-sync", nstatus->role);
- break;
- case WL_NAN_ROLE_MASTER:
- printf("> role: %s (%d)\n", "master", nstatus->role);
- break;
- case WL_NAN_ROLE_ANCHOR_MASTER:
- printf("> role: %s (%d)\n", "anchor-master", nstatus->role);
- break;
- default:
- printf("> role: %s (%d)\n", "undefined", nstatus->role);
- break;
- }
- printf("> social channels: %d, %d\n",
- nstatus->social_chans[0], nstatus->social_chans[1]);
- printf("> master_rank: " NMRSTR "\n", NMR2STR(nstatus->mr));
- printf("> amr : " NMRSTR "\n", NMR2STR(nstatus->amr));
- printf("> hop_count: %d\n", nstatus->hop_count);
- printf("> ambtt: %d\n", nstatus->ambtt);
- }
- static void
- wl_cfgnan_clear_nan_event_data(struct bcm_cfg80211 *cfg,
- nan_event_data_t *nan_event_data)
- {
- if (nan_event_data) {
- if (nan_event_data->tx_match_filter.data) {
- MFREE(cfg->osh, nan_event_data->tx_match_filter.data,
- nan_event_data->tx_match_filter.dlen);
- nan_event_data->tx_match_filter.data = NULL;
- }
- if (nan_event_data->rx_match_filter.data) {
- MFREE(cfg->osh, nan_event_data->rx_match_filter.data,
- nan_event_data->rx_match_filter.dlen);
- nan_event_data->rx_match_filter.data = NULL;
- }
- if (nan_event_data->svc_info.data) {
- MFREE(cfg->osh, nan_event_data->svc_info.data,
- nan_event_data->svc_info.dlen);
- nan_event_data->svc_info.data = NULL;
- }
- if (nan_event_data->sde_svc_info.data) {
- MFREE(cfg->osh, nan_event_data->sde_svc_info.data,
- nan_event_data->sde_svc_info.dlen);
- nan_event_data->sde_svc_info.data = NULL;
- }
- MFREE(cfg->osh, nan_event_data, sizeof(*nan_event_data));
- }
- }
- #ifdef RTT_SUPPORT
- /*
- * Triggers rtt work thread
- * if geofence rtt pending,
- * clears ranging instance
- * otherwise
- */
- void
- wl_cfgnan_reset_geofence_ranging(struct bcm_cfg80211 *cfg,
- nan_ranging_inst_t * rng_inst, int sched_reason)
- {
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- u8 rtt_invalid_reason = RTT_STATE_VALID;
- rtt_geofence_target_info_t *geofence_target = NULL;
- rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
- int8 cur_idx = DHD_RTT_INVALID_TARGET_INDEX;
- int8 index = DHD_RTT_INVALID_TARGET_INDEX;
- bool geofence_state = dhd_rtt_get_geofence_rtt_state(dhd);
- bool retry = FALSE;
- WL_INFORM_MEM(("wl_cfgnan_reset_geofence_ranging, sched_reason = %d, cur_idx = %d\n",
- sched_reason, rtt_status->geofence_cfg.cur_target_idx));
- cur_idx = dhd_rtt_get_geofence_cur_target_idx(dhd);
- if (cur_idx == -1) {
- WL_INFORM_MEM(("wl_cfgnan_reset_geofence_ranging, "
- "Removing Ranging Instance " MACDBG "\n",
- MAC2STRDBG(&(rng_inst->peer_addr))));
- bzero(rng_inst, sizeof(*rng_inst));
- /* Cancel pending retry timer if any */
- if (delayed_work_pending(&rtt_status->rtt_retry_timer)) {
- cancel_delayed_work(&rtt_status->rtt_retry_timer);
- }
- goto exit;
- }
- /* Get current geofencing target */
- geofence_target = dhd_rtt_get_geofence_current_target(dhd);
- /* get target index for cur ranging inst */
- dhd_rtt_get_geofence_target(dhd,
- &rng_inst->peer_addr, &index);
- if (cur_idx == index) {
- /* Reset incoming Ranging instance */
- rng_inst->range_type = RTT_TYPE_NAN_GEOFENCE;
- rng_inst->range_status = NAN_RANGING_REQUIRED;
- if ((sched_reason != RTT_SCHED_RNG_RPT_GEOFENCE) &&
- (sched_reason != RTT_SCHED_RTT_RETRY_GEOFENCE)) {
- rng_inst->prev_distance_mm = INVALID_DISTANCE;
- }
- } else {
- if (index == DHD_RTT_INVALID_TARGET_INDEX) {
- /* Remove incoming Ranging instance */
- WL_INFORM_MEM(("Removing Ranging Instance " MACDBG "\n",
- MAC2STRDBG(&(rng_inst->peer_addr))));
- bzero(rng_inst, sizeof(*rng_inst));
- } else {
- /* Reset incoming Ranging instance */
- rng_inst->range_type = RTT_TYPE_NAN_GEOFENCE;
- rng_inst->range_status = NAN_RANGING_REQUIRED;
- if ((sched_reason != RTT_SCHED_RNG_RPT_GEOFENCE) &&
- (sched_reason != RTT_SCHED_RTT_RETRY_GEOFENCE)) {
- rng_inst->prev_distance_mm = INVALID_DISTANCE;
- }
- }
- /* Create range inst if not present and reset explicitly */
- rng_inst = wl_cfgnan_get_ranging_inst(cfg,
- &geofence_target->peer_addr, NAN_RANGING_ROLE_INITIATOR);
- }
- /* Retry later if
- * already geofence running
- * or Directed RTT in progress
- * or Invalid RTT state like
- * NDP with Peer
- */
- if ((geofence_state == TRUE) ||
- (!RTT_IS_STOPPED(rtt_status)) ||
- (rtt_invalid_reason != RTT_STATE_VALID)) {
- /* Not in valid RTT state, retry over a timer */
- retry = TRUE;
- }
- if (cur_idx == 0 && sched_reason == RTT_SCHED_RNG_RPT_GEOFENCE) {
- /* First Target again after all done, retry over a timer */
- retry = TRUE;
- }
- if (retry) {
- /* Move to first target and retry over a timer */
- WL_DBG(("Retry over a timer, cur_idx = %d\n",
- rtt_status->geofence_cfg.cur_target_idx));
- /* schedule proxd retry timer */
- schedule_delayed_work(&rtt_status->rtt_retry_timer,
- msecs_to_jiffies(DHD_RTT_RETRY_TIMER_INTERVAL_MS));
- goto exit;
- }
- /* schedule RTT */
- dhd_rtt_schedule_rtt_work_thread(dhd, sched_reason);
- exit:
- return;
- }
- static bool
- wl_check_range_role_concurrency(dhd_pub_t *dhd, nan_ranging_inst_t *rng_inst)
- {
- ASSERT(rng_inst);
- if ((dhd_rtt_get_role_concurrency_state(dhd) == TRUE) &&
- (rng_inst->num_svc_ctx > 0)) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- static void
- wl_cfgnan_resolve_ranging_role_concurrecny(dhd_pub_t *dhd,
- nan_ranging_inst_t *rng_inst)
- {
- /* Update rang_inst to initiator and resolve role concurrency */
- rng_inst->range_role = NAN_RANGING_ROLE_INITIATOR;
- dhd_rtt_set_role_concurrency_state(dhd, FALSE);
- }
- #endif /* RTT_SUPPORT */
- s32
- wl_cfgnan_notify_nan_status(struct bcm_cfg80211 *cfg,
- bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *event, void *event_data)
- {
- uint16 data_len;
- uint32 event_num;
- s32 event_type;
- int hal_event_id = 0;
- nan_event_data_t *nan_event_data = NULL;
- nan_parse_event_ctx_t nan_event_ctx;
- uint16 tlvs_offset = 0;
- uint16 nan_opts_len = 0;
- uint8 *tlv_buf;
- s32 ret = BCME_OK;
- bcm_xtlv_opts_t xtlv_opt = BCM_IOV_CMD_OPT_ALIGN32;
- uint32 status;
- nan_svc_info_t *svc;
- UNUSED_PARAMETER(wl_nan_print_status);
- UNUSED_PARAMETER(status);
- NAN_DBG_ENTER();
- NAN_MUTEX_LOCK();
- if (!event || !event_data) {
- WL_ERR(("event data is NULL\n"));
- ret = -EINVAL;
- goto exit;
- }
- event_type = ntoh32(event->event_type);
- event_num = ntoh32(event->reason);
- data_len = ntoh32(event->datalen);
- if (NAN_INVALID_EVENT(event_num)) {
- WL_ERR(("unsupported event, num: %d, event type: %d\n", event_num, event_type));
- ret = -EINVAL;
- goto exit;
- }
- WL_DBG((">> Nan Event Received: %s (num=%d, len=%d)\n",
- nan_event_to_str(event_num), event_num, data_len));
- #ifdef WL_NAN_DEBUG
- prhex("nan_event_data:", event_data, data_len);
- #endif /* WL_NAN_DEBUG */
- if (!cfg->nan_init_state) {
- WL_ERR(("nan is not in initialized state, dropping nan related events\n"));
- ret = BCME_OK;
- goto exit;
- }
- nan_event_data = MALLOCZ(cfg->osh, sizeof(*nan_event_data));
- if (!nan_event_data) {
- WL_ERR(("%s: memory allocation failed\n", __func__));
- goto exit;
- }
- nan_event_ctx.cfg = cfg;
- nan_event_ctx.nan_evt_data = nan_event_data;
- /*
- * send as preformatted hex string
- * EVENT_NAN <event_type> <tlv_hex_string>
- */
- switch (event_num) {
- case WL_NAN_EVENT_START:
- case WL_NAN_EVENT_MERGE:
- case WL_NAN_EVENT_ROLE: {
- /* get nan status info as-is */
- bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
- wl_nan_conf_status_t *nstatus = (wl_nan_conf_status_t *)xtlv->data;
- WL_INFORM_MEM((">> Nan Mac Event Received: %s (num=%d, len=%d)\n",
- nan_event_to_str(event_num), event_num, data_len));
- WL_INFORM_MEM(("Nan Device Role %s\n", nan_role_to_str(nstatus->role)));
- /* Mapping to common struct between DHD and HAL */
- nan_event_data->enabled = nstatus->enabled;
- ret = memcpy_s(&nan_event_data->local_nmi, ETHER_ADDR_LEN,
- &nstatus->nmi, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nmi\n"));
- goto exit;
- }
- ret = memcpy_s(&nan_event_data->clus_id, ETHER_ADDR_LEN,
- &nstatus->cid, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy cluster id\n"));
- goto exit;
- }
- nan_event_data->nan_de_evt_type = event_num;
- #ifdef WL_NAN_DEBUG
- wl_nan_print_status(nstatus);
- #endif /* WL_NAN_DEBUG */
- if (event_num == WL_NAN_EVENT_START) {
- OSL_SMP_WMB();
- cfg->nancfg.nan_event_recvd = true;
- OSL_SMP_WMB();
- wake_up(&cfg->nancfg.nan_event_wait);
- }
- hal_event_id = GOOGLE_NAN_EVENT_DE_EVENT;
- break;
- }
- case WL_NAN_EVENT_TERMINATED: {
- bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
- wl_nan_ev_terminated_t *pev = (wl_nan_ev_terminated_t *)xtlv->data;
- /* Mapping to common struct between DHD and HAL */
- WL_TRACE(("Instance ID: %d\n", pev->instance_id));
- nan_event_data->local_inst_id = pev->instance_id;
- WL_TRACE(("Service Type: %d\n", pev->svctype));
- #ifdef WL_NAN_DISC_CACHE
- if (pev->svctype == NAN_SC_SUBSCRIBE) {
- wl_cfgnan_remove_disc_result(cfg, pev->instance_id);
- }
- #endif /* WL_NAN_DISC_CACHE */
- /* Mapping reason code of FW to status code of framework */
- if (pev->reason == NAN_TERM_REASON_TIMEOUT ||
- pev->reason == NAN_TERM_REASON_USER_REQ ||
- pev->reason == NAN_TERM_REASON_COUNT_REACHED) {
- nan_event_data->status = NAN_STATUS_SUCCESS;
- ret = memcpy_s(nan_event_data->nan_reason,
- sizeof(nan_event_data->nan_reason),
- "NAN_STATUS_SUCCESS",
- strlen("NAN_STATUS_SUCCESS"));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nan_reason\n"));
- goto exit;
- }
- } else {
- nan_event_data->status = NAN_STATUS_INTERNAL_FAILURE;
- ret = memcpy_s(nan_event_data->nan_reason,
- sizeof(nan_event_data->nan_reason),
- "NAN_STATUS_INTERNAL_FAILURE",
- strlen("NAN_STATUS_INTERNAL_FAILURE"));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nan_reason\n"));
- goto exit;
- }
- }
- if (pev->svctype == NAN_SC_SUBSCRIBE) {
- hal_event_id = GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED;
- } else {
- hal_event_id = GOOGLE_NAN_EVENT_PUBLISH_TERMINATED;
- }
- #ifdef WL_NAN_DISC_CACHE
- if (pev->reason != NAN_TERM_REASON_USER_REQ) {
- wl_cfgnan_clear_svc_ranging_inst(cfg, pev->instance_id);
- /* terminate ranging sessions */
- wl_cfgnan_terminate_ranging_sessions(bcmcfg_to_prmry_ndev(cfg),
- cfg, pev->instance_id);
- }
- #endif /* WL_NAN_DISC_CACHE */
- break;
- }
- case WL_NAN_EVENT_RECEIVE: {
- nan_opts_len = data_len;
- hal_event_id = GOOGLE_NAN_EVENT_FOLLOWUP;
- xtlv_opt = BCM_IOV_CMD_OPT_ALIGN_NONE;
- break;
- }
- case WL_NAN_EVENT_TXS: {
- bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
- wl_nan_event_txs_t *txs = (wl_nan_event_txs_t *)xtlv->data;
- wl_nan_event_sd_txs_t *txs_sd = NULL;
- if (txs->status == WL_NAN_TXS_SUCCESS) {
- WL_INFORM_MEM(("TXS success for type %d token %d\n",
- txs->type, txs->host_seq));
- nan_event_data->status = NAN_STATUS_SUCCESS;
- ret = memcpy_s(nan_event_data->nan_reason,
- sizeof(nan_event_data->nan_reason),
- "NAN_STATUS_SUCCESS",
- strlen("NAN_STATUS_SUCCESS"));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nan_reason\n"));
- goto exit;
- }
- } else {
- /* TODO : populate status based on reason codes
- For now adding it as no ACK, so that app/framework can retry
- */
- WL_INFORM_MEM(("TXS failed for type %d status %d token %d\n",
- txs->type, txs->status, txs->host_seq));
- nan_event_data->status = NAN_STATUS_NO_OTA_ACK;
- ret = memcpy_s(nan_event_data->nan_reason,
- sizeof(nan_event_data->nan_reason),
- "NAN_STATUS_NO_OTA_ACK",
- strlen("NAN_STATUS_NO_OTA_ACK"));
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy nan_reason\n"));
- goto exit;
- }
- }
- nan_event_data->reason = txs->reason_code;
- nan_event_data->token = txs->host_seq;
- if (txs->type == WL_NAN_FRM_TYPE_FOLLOWUP) {
- hal_event_id = GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND;
- xtlv = (bcm_xtlv_t *)(txs->opt_tlvs);
- if (txs->opt_tlvs_len && xtlv->id == WL_NAN_XTLV_SD_TXS) {
- txs_sd = (wl_nan_event_sd_txs_t*)xtlv->data;
- nan_event_data->local_inst_id = txs_sd->inst_id;
- } else {
- WL_ERR(("Invalid params in TX status for trasnmit followup"));
- ret = -EINVAL;
- goto exit;
- }
- } else { /* TODO: add for other frame types if required */
- ret = -EINVAL;
- goto exit;
- }
- break;
- }
- case WL_NAN_EVENT_DISCOVERY_RESULT: {
- nan_opts_len = data_len;
- hal_event_id = GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH;
- xtlv_opt = BCM_IOV_CMD_OPT_ALIGN_NONE;
- break;
- }
- #ifdef WL_NAN_DISC_CACHE
- case WL_NAN_EVENT_DISC_CACHE_TIMEOUT: {
- bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
- wl_nan_ev_disc_cache_timeout_t *cache_data =
- (wl_nan_ev_disc_cache_timeout_t *)xtlv->data;
- wl_nan_disc_expired_cache_entry_t *cache_entry = NULL;
- uint16 xtlv_len = xtlv->len;
- uint8 entry_idx = 0;
- if (xtlv->id == WL_NAN_XTLV_SD_DISC_CACHE_TIMEOUT) {
- xtlv_len = xtlv_len -
- OFFSETOF(wl_nan_ev_disc_cache_timeout_t, cache_exp_list);
- while ((entry_idx < cache_data->count) &&
- (xtlv_len >= sizeof(*cache_entry))) {
- cache_entry = &cache_data->cache_exp_list[entry_idx];
- /* Invalidate local cache info */
- wl_cfgnan_remove_disc_result(cfg, cache_entry->l_sub_id);
- xtlv_len = xtlv_len - sizeof(*cache_entry);
- entry_idx++;
- }
- }
- break;
- }
- case WL_NAN_EVENT_RNG_REQ_IND: {
- wl_nan_ev_rng_req_ind_t *rng_ind;
- bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
- nan_opts_len = data_len;
- rng_ind = (wl_nan_ev_rng_req_ind_t *)xtlv->data;
- xtlv_opt = BCM_IOV_CMD_OPT_ALIGN_NONE;
- WL_INFORM_MEM(("Received WL_NAN_EVENT_RNG_REQ_IND range_id %d"
- " peer:" MACDBG "\n", rng_ind->rng_id,
- MAC2STRDBG(&rng_ind->peer_m_addr)));
- #ifdef RTT_SUPPORT
- ret = wl_cfgnan_handle_ranging_ind(cfg, rng_ind);
- #endif /* RTT_SUPPORT */
- /* no need to event to HAL */
- goto exit;
- }
- case WL_NAN_EVENT_RNG_TERM_IND: {
- bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- nan_ranging_inst_t *rng_inst;
- wl_nan_ev_rng_term_ind_t *range_term = (wl_nan_ev_rng_term_ind_t *)xtlv->data;
- #ifdef RTT_SUPPORT
- int8 index = -1;
- rtt_geofence_target_info_t* geofence_target;
- #endif /* RTT_SUPPORT */
- BCM_REFERENCE(dhd);
- WL_INFORM_MEM(("Received WL_NAN_EVENT_RNG_TERM_IND peer: " MACDBG ", "
- " Reason Code: %d\n", MAC2STRDBG(&range_term->peer_m_addr),
- range_term->reason_code));
- rng_inst = wl_cfgnan_check_for_ranging(cfg, &range_term->peer_m_addr);
- if (rng_inst) {
- #ifdef RTT_SUPPORT
- if (rng_inst->range_type == RTT_TYPE_NAN_DIRECTED) {
- dhd_rtt_handle_nan_rtt_session_end(dhd, &rng_inst->peer_addr);
- } else if (rng_inst->range_type == RTT_TYPE_NAN_GEOFENCE) {
- /* Set geofence RTT in progress state to false */
- /*
- * ToDo:
- * Check for reason code,
- * Accordingly, if we can attempt retry
- */
- geofence_target = dhd_rtt_get_geofence_target(dhd,
- &rng_inst->peer_addr, &index);
- if (geofence_target) {
- dhd_rtt_remove_geofence_target(dhd,
- &geofence_target->peer_addr);
- }
- WL_TRACE(("Reset the state on terminate\n"));
- /* If the target was the geofence queue head */
- dhd_rtt_set_geofence_rtt_state(dhd, FALSE);
- }
- if (rng_inst->range_role == NAN_RANGING_ROLE_RESPONDER &&
- wl_check_range_role_concurrency(dhd, rng_inst)) {
- /* Resolve role concurrency */
- wl_cfgnan_resolve_ranging_role_concurrecny(dhd, rng_inst);
- }
- /* Dont abolish rng_inst if geofence rtt pending for peer */
- wl_cfgnan_reset_geofence_ranging(cfg, rng_inst, RTT_SCHED_RNG_TERM);
- #endif /* RTT_SUPPORT */
- }
- break;
- }
- #endif /* WL_NAN_DISC_CACHE */
- /*
- * Data path events data are received in common event struct,
- * Handling all the events as part of one case, hence fall through is intentional
- */
- case WL_NAN_EVENT_PEER_DATAPATH_IND:
- case WL_NAN_EVENT_DATAPATH_ESTB:
- case WL_NAN_EVENT_DATAPATH_END: {
- ret = wl_nan_dp_cmn_event_data(cfg, event_data, data_len,
- &tlvs_offset, &nan_opts_len,
- event_num, &hal_event_id, nan_event_data);
- /* Avoiding optional param parsing for DP END Event */
- if (event_num == WL_NAN_EVENT_DATAPATH_END) {
- nan_opts_len = 0;
- xtlv_opt = BCM_IOV_CMD_OPT_ALIGN_NONE;
- }
- if (unlikely(ret)) {
- WL_ERR(("nan dp common event data parse failed\n"));
- goto exit;
- }
- break;
- }
- default:
- WL_ERR_RLMT(("WARNING: unimplemented NAN APP EVENT = %d\n", event_num));
- ret = BCME_ERROR;
- goto exit;
- }
- if (nan_opts_len) {
- tlv_buf = (uint8 *)event_data + tlvs_offset;
- /* Extract event data tlvs and pass their resp to cb fn */
- ret = bcm_unpack_xtlv_buf((void *)&nan_event_ctx, (const uint8*)tlv_buf,
- nan_opts_len, xtlv_opt, wl_cfgnan_set_vars_cbfn);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to unpack tlv data, ret=%d\n", ret));
- }
- }
- #ifdef WL_NAN_DISC_CACHE
- if (hal_event_id == GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH) {
- #ifdef RTT_SUPPORT
- u8 rtt_invalid_reason = RTT_STATE_VALID;
- bool role_concur_state = 0;
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- #endif /* RTT_SUPPORT */
- u16 update_flags = 0;
- WL_TRACE(("Cache disc res\n"));
- ret = wl_cfgnan_cache_disc_result(cfg, nan_event_data, &update_flags);
- if (ret) {
- WL_ERR(("Failed to cache disc result ret %d\n", ret));
- }
- if (nan_event_data->sde_control_flag & NAN_SDE_CF_RANGING_REQUIRED) {
- ret = wl_cfgnan_check_disc_result_for_ranging(cfg, nan_event_data);
- if (ret == BCME_OK) {
- #ifdef RTT_SUPPORT
- rtt_invalid_reason = dhd_rtt_invalid_states
- (bcmcfg_to_prmry_ndev(cfg), &nan_event_data->remote_nmi);
- role_concur_state = dhd_rtt_get_role_concurrency_state(dhd);
- /*
- * If instant RTT not possible,
- * send discovery result instantly like
- * incase of invalid rtt state as
- * NDP connected/connecting or role_concurrency
- * on, otherwise, disc result will be posted
- * on ranging report event
- */
- if (rtt_invalid_reason == RTT_STATE_VALID &&
- role_concur_state == FALSE) {
- /* Avoid sending disc result instantly */
- goto exit;
- }
- #endif /* RTT_SUPPORT */
- } else {
- /* TODO: should we terminate service if ranging fails ? */
- WL_INFORM_MEM(("Ranging failed or not required, " MACDBG
- " sub_id:%d , pub_id:%d\n",
- MAC2STRDBG(&nan_event_data->remote_nmi),
- nan_event_data->sub_id, nan_event_data->pub_id));
- }
- } else {
- nan_svc_info_t *svc_info = wl_cfgnan_get_svc_inst(cfg,
- nan_event_data->sub_id, 0);
- if (svc_info && svc_info->ranging_required &&
- (update_flags & NAN_DISC_CACHE_PARAM_SDE_CONTROL)) {
- wl_cfgnan_clear_svc_ranging_inst(cfg, nan_event_data->sub_id);
- /* terminate ranging sessions for this svc, if any */
- wl_cfgnan_terminate_ranging_sessions(bcmcfg_to_prmry_ndev(cfg),
- cfg, nan_event_data->sub_id);
- }
- WL_DBG(("Ranging sessions terminated for svc update or not required\n"));
- }
- /*
- * If tx match filter is present as part of active subscribe, keep same filter
- * values in discovery results also.
- */
- if (nan_event_data->sub_id == nan_event_data->requestor_id) {
- svc = wl_cfgnan_get_svc_inst(cfg, nan_event_data->sub_id, 0);
- if (svc && svc->tx_match_filter_len) {
- nan_event_data->tx_match_filter.dlen = svc->tx_match_filter_len;
- nan_event_data->tx_match_filter.data =
- MALLOCZ(cfg->osh, svc->tx_match_filter_len);
- if (!nan_event_data->tx_match_filter.data) {
- WL_ERR(("%s: tx_match_filter_data alloc failed\n",
- __FUNCTION__));
- nan_event_data->tx_match_filter.dlen = 0;
- ret = -ENOMEM;
- goto exit;
- }
- ret = memcpy_s(nan_event_data->tx_match_filter.data,
- nan_event_data->tx_match_filter.dlen,
- svc->tx_match_filter, svc->tx_match_filter_len);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy tx match filter data\n"));
- goto exit;
- }
- }
- }
- }
- #endif /* WL_NAN_DISC_CACHE */
- WL_TRACE(("Send up %s (%d) data to HAL, hal_event_id=%d\n",
- nan_event_to_str(event_num), event_num, hal_event_id));
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
- ret = wl_cfgvendor_send_nan_event(cfg->wdev->wiphy, bcmcfg_to_prmry_ndev(cfg),
- hal_event_id, nan_event_data);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to send event to nan hal, %s (%d)\n",
- nan_event_to_str(event_num), event_num));
- }
- #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
- exit:
- wl_cfgnan_clear_nan_event_data(cfg, nan_event_data);
- NAN_MUTEX_UNLOCK();
- NAN_DBG_EXIT();
- return ret;
- }
- #ifdef WL_NAN_DISC_CACHE
- static int
- wl_cfgnan_cache_disc_result(struct bcm_cfg80211 *cfg, void * data,
- u16 *disc_cache_update_flags)
- {
- nan_event_data_t* disc = (nan_event_data_t*)data;
- int i, add_index = 0;
- int ret = BCME_OK;
- nan_disc_result_cache *disc_res = cfg->nan_disc_cache;
- *disc_cache_update_flags = 0;
- if (!cfg->nan_enable) {
- WL_DBG(("nan not enabled"));
- return BCME_NOTENABLED;
- }
- if (cfg->nan_disc_count == NAN_MAX_CACHE_DISC_RESULT) {
- WL_DBG(("cache full"));
- ret = BCME_NORESOURCE;
- goto done;
- }
- for (i = 0; i < NAN_MAX_CACHE_DISC_RESULT; i++) {
- if (!disc_res[i].valid) {
- add_index = i;
- continue;
- }
- if (!memcmp(&disc_res[i].peer, &disc->remote_nmi, ETHER_ADDR_LEN) &&
- !memcmp(disc_res[i].svc_hash, disc->svc_name, WL_NAN_SVC_HASH_LEN)) {
- WL_DBG(("cache entry already present, i = %d", i));
- /* Update needed parameters here */
- if (disc_res[i].sde_control_flag != disc->sde_control_flag) {
- disc_res[i].sde_control_flag = disc->sde_control_flag;
- *disc_cache_update_flags |= NAN_DISC_CACHE_PARAM_SDE_CONTROL;
- }
- ret = BCME_OK; /* entry already present */
- goto done;
- }
- }
- WL_DBG(("adding cache entry: add_index = %d\n", add_index));
- disc_res[add_index].valid = 1;
- disc_res[add_index].pub_id = disc->pub_id;
- disc_res[add_index].sub_id = disc->sub_id;
- disc_res[add_index].publish_rssi = disc->publish_rssi;
- disc_res[add_index].peer_cipher_suite = disc->peer_cipher_suite;
- disc_res[add_index].sde_control_flag = disc->sde_control_flag;
- ret = memcpy_s(&disc_res[add_index].peer, ETHER_ADDR_LEN,
- &disc->remote_nmi, ETHER_ADDR_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy remote nmi\n"));
- goto done;
- }
- ret = memcpy_s(disc_res[add_index].svc_hash, WL_NAN_SVC_HASH_LEN,
- disc->svc_name, WL_NAN_SVC_HASH_LEN);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy svc hash\n"));
- goto done;
- }
- if (disc->svc_info.dlen && disc->svc_info.data) {
- disc_res[add_index].svc_info.dlen = disc->svc_info.dlen;
- disc_res[add_index].svc_info.data =
- MALLOCZ(cfg->osh, disc_res[add_index].svc_info.dlen);
- if (!disc_res[add_index].svc_info.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- disc_res[add_index].svc_info.dlen = 0;
- ret = BCME_NOMEM;
- goto done;
- }
- ret = memcpy_s(disc_res[add_index].svc_info.data, disc_res[add_index].svc_info.dlen,
- disc->svc_info.data, disc->svc_info.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy svc info\n"));
- goto done;
- }
- }
- if (disc->tx_match_filter.dlen && disc->tx_match_filter.data) {
- disc_res[add_index].tx_match_filter.dlen = disc->tx_match_filter.dlen;
- disc_res[add_index].tx_match_filter.data =
- MALLOCZ(cfg->osh, disc_res[add_index].tx_match_filter.dlen);
- if (!disc_res[add_index].tx_match_filter.data) {
- WL_ERR(("%s: memory allocation failed\n", __FUNCTION__));
- disc_res[add_index].tx_match_filter.dlen = 0;
- ret = BCME_NOMEM;
- goto done;
- }
- ret = memcpy_s(disc_res[add_index].tx_match_filter.data,
- disc_res[add_index].tx_match_filter.dlen,
- disc->tx_match_filter.data, disc->tx_match_filter.dlen);
- if (ret != BCME_OK) {
- WL_ERR(("Failed to copy tx match filter\n"));
- goto done;
- }
- }
- cfg->nan_disc_count++;
- WL_DBG(("cfg->nan_disc_count = %d\n", cfg->nan_disc_count));
- done:
- return ret;
- }
- /* Sending command to FW for clearing discovery cache info in FW */
- static int
- wl_cfgnan_clear_disc_cache(struct bcm_cfg80211 *cfg, wl_nan_instance_id_t sub_id)
- {
- s32 ret = BCME_OK;
- uint16 nan_buf_size = NAN_IOCTL_BUF_SIZE;
- uint32 status;
- uint8 resp_buf[NAN_IOCTL_BUF_SIZE];
- uint8 buf[NAN_IOCTL_BUF_SIZE];
- bcm_iov_batch_buf_t *nan_buf;
- bcm_iov_batch_subcmd_t *sub_cmd;
- uint16 subcmd_len;
- /* Same src and dest len here */
- memset_s(buf, sizeof(buf), 0, sizeof(buf));
- nan_buf = (bcm_iov_batch_buf_t*)buf;
- nan_buf->version = htol16(WL_NAN_IOV_BATCH_VERSION);
- nan_buf->count = 0;
- nan_buf_size -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
- sub_cmd = (bcm_iov_batch_subcmd_t *)(&nan_buf->cmds[0]);
- ret = wl_cfg_nan_check_cmd_len(nan_buf_size,
- sizeof(sub_id), &subcmd_len);
- if (unlikely(ret)) {
- WL_ERR(("nan_sub_cmd check failed\n"));
- goto fail;
- }
- /* Fill the sub_command block */
- sub_cmd->id = htod16(WL_NAN_CMD_SD_DISC_CACHE_CLEAR);
- sub_cmd->len = sizeof(sub_cmd->u.options) + sizeof(sub_id);
- sub_cmd->u.options = htol32(BCM_XTLV_OPTION_ALIGN32);
- /* Data size len vs buffer len check is already done above.
- * So, short buffer error is impossible.
- */
- (void)memcpy_s(sub_cmd->data, (nan_buf_size - OFFSETOF(bcm_iov_batch_subcmd_t, data)),
- &sub_id, sizeof(sub_id));
- /* adjust iov data len to the end of last data record */
- nan_buf_size -= (subcmd_len);
- nan_buf->count++;
- nan_buf->is_set = true;
- nan_buf_size = NAN_IOCTL_BUF_SIZE - nan_buf_size;
- /* Same src and dest len here */
- memset_s(resp_buf, sizeof(resp_buf), 0, sizeof(resp_buf));
- ret = wl_cfgnan_execute_ioctl(bcmcfg_to_prmry_ndev(cfg), cfg,
- nan_buf, nan_buf_size, &status,
- (void*)resp_buf, NAN_IOCTL_BUF_SIZE);
- if (unlikely(ret) || unlikely(status)) {
- WL_ERR(("Disc cache clear handler failed ret %d status %d\n",
- ret, status));
- goto fail;
- }
- fail:
- return ret;
- }
- static int wl_cfgnan_remove_disc_result(struct bcm_cfg80211 *cfg,
- uint8 local_subid)
- {
- int i;
- int ret = BCME_NOTFOUND;
- nan_disc_result_cache *disc_res = cfg->nan_disc_cache;
- if (!cfg->nan_enable) {
- WL_DBG(("nan not enabled\n"));
- ret = BCME_NOTENABLED;
- goto done;
- }
- for (i = 0; i < NAN_MAX_CACHE_DISC_RESULT; i++) {
- if ((disc_res[i].valid) && (disc_res[i].sub_id == local_subid)) {
- WL_TRACE(("make cache entry invalid\n"));
- if (disc_res[i].tx_match_filter.data) {
- MFREE(cfg->osh, disc_res[i].tx_match_filter.data,
- disc_res[i].tx_match_filter.dlen);
- }
- if (disc_res[i].svc_info.data) {
- MFREE(cfg->osh, disc_res[i].svc_info.data,
- disc_res[i].svc_info.dlen);
- }
- memset_s(&disc_res[i], sizeof(disc_res[i]), 0, sizeof(disc_res[i]));
- cfg->nan_disc_count--;
- ret = BCME_OK;
- }
- }
- WL_DBG(("couldn't find entry\n"));
- done:
- return ret;
- }
- static nan_disc_result_cache *
- wl_cfgnan_get_disc_result(struct bcm_cfg80211 *cfg, uint8 remote_pubid,
- struct ether_addr *peer)
- {
- int i;
- nan_disc_result_cache *disc_res = cfg->nan_disc_cache;
- if (remote_pubid) {
- for (i = 0; i < NAN_MAX_CACHE_DISC_RESULT; i++) {
- if ((disc_res[i].pub_id == remote_pubid) &&
- !memcmp(&disc_res[i].peer, peer, ETHER_ADDR_LEN)) {
- WL_DBG(("Found entry: i = %d\n", i));
- return &disc_res[i];
- }
- }
- } else {
- for (i = 0; i < NAN_MAX_CACHE_DISC_RESULT; i++) {
- if (!memcmp(&disc_res[i].peer, peer, ETHER_ADDR_LEN)) {
- WL_DBG(("Found entry: %d\n", i));
- return &disc_res[i];
- }
- }
- }
- return NULL;
- }
- #endif /* WL_NAN_DISC_CACHE */
- static void
- wl_cfgnan_update_dp_mask(struct bcm_cfg80211 *cfg, bool enable, u8 nan_dp_id)
- {
- #ifdef ARP_OFFLOAD_SUPPORT
- dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
- #endif /* ARP_OFFLOAD_SUPPORT */
- /* As of now, we don't see a need to know which ndp is active.
- * so just keep tracking of ndp via count. If we need to know
- * the status of each ndp based on ndp id, we need to change
- * this implementation to use a bit mask.
- */
- if (!dhd) {
- WL_ERR(("dhd pub null!\n"));
- return;
- }
- if (enable) {
- /* On first NAN DP indication, disable ARP. */
- #ifdef ARP_OFFLOAD_SUPPORT
- if (!cfg->nan_dp_mask) {
- dhd_arp_offload_set(dhd, 0);
- dhd_arp_offload_enable(dhd, false);
- }
- #endif /* ARP_OFFLOAD_SUPPORT */
- cfg->nan_dp_mask |= (0x1 << nan_dp_id);
- } else {
- cfg->nan_dp_mask &= ~(0x1 << nan_dp_id);
- #ifdef ARP_OFFLOAD_SUPPORT
- if (!cfg->nan_dp_mask) {
- /* If NAN DP count becomes zero and if there
- * are no conflicts, enable back ARP offload.
- * As of now, the conflicting interfaces are AP
- * and P2P. But NAN + P2P/AP concurrency is not
- * supported.
- */
- dhd_arp_offload_set(dhd, dhd_arp_mode);
- dhd_arp_offload_enable(dhd, true);
- }
- #endif /* ARP_OFFLOAD_SUPPORT */
- }
- WL_INFORM_MEM(("NAN_DP_MASK:0x%x\n", cfg->nan_dp_mask));
- }
- bool
- wl_cfgnan_is_dp_active(struct net_device *ndev)
- {
- struct bcm_cfg80211 *cfg;
- bool nan_dp;
- if (!ndev || !ndev->ieee80211_ptr) {
- WL_ERR(("ndev/wdev null\n"));
- return false;
- }
- cfg = wiphy_priv(ndev->ieee80211_ptr->wiphy);
- nan_dp = cfg->nan_dp_mask ? true : false;
- WL_DBG(("NAN DP status:%d\n", nan_dp));
- return nan_dp;
- }
- s32
- wl_cfgnan_get_ndi_idx(struct bcm_cfg80211 *cfg)
- {
- int i;
- for (i = 0; i < NAN_MAX_NDI; i++) {
- if (!cfg->nancfg.ndi[i].in_use) {
- /* Free interface, use it */
- return i;
- }
- }
- /* Don't have a free interface */
- return WL_INVALID;
- }
- s32
- wl_cfgnan_add_ndi_data(struct bcm_cfg80211 *cfg, s32 idx, char *name)
- {
- u16 len;
- if (!name || (idx < 0) || (idx >= NAN_MAX_NDI)) {
- return -EINVAL;
- }
- /* Ensure ifname string size <= IFNAMSIZ including null termination */
- len = MIN(strlen(name), (IFNAMSIZ - 1));
- strncpy(cfg->nancfg.ndi[idx].ifname, name, len);
- cfg->nancfg.ndi[idx].ifname[len] = '\0';
- cfg->nancfg.ndi[idx].in_use = true;
- cfg->nancfg.ndi[idx].created = false;
- /* Don't have a free interface */
- return WL_INVALID;
- }
- s32
- wl_cfgnan_del_ndi_data(struct bcm_cfg80211 *cfg, char *name)
- {
- u16 len;
- int i;
- if (!name) {
- return -EINVAL;
- }
- len = MIN(strlen(name), IFNAMSIZ);
- for (i = 0; i < NAN_MAX_NDI; i++) {
- if (strncmp(cfg->nancfg.ndi[i].ifname, name, len) == 0) {
- memset_s(&cfg->nancfg.ndi[i].ifname, IFNAMSIZ,
- 0x0, IFNAMSIZ);
- cfg->nancfg.ndi[i].in_use = false;
- cfg->nancfg.ndi[i].created = false;
- cfg->nancfg.ndi[i].nan_ndev = NULL;
- return i;
- }
- }
- return -EINVAL;
- }
- struct wl_ndi_data *
- wl_cfgnan_get_ndi_data(struct bcm_cfg80211 *cfg, char *name)
- {
- u16 len;
- int i;
- if (!name) {
- return NULL;
- }
- len = MIN(strlen(name), IFNAMSIZ);
- for (i = 0; i < NAN_MAX_NDI; i++) {
- if (strncmp(cfg->nancfg.ndi[i].ifname, name, len) == 0) {
- return &cfg->nancfg.ndi[i];
- }
- }
- return NULL;
- }
- s32
- wl_cfgnan_delete_ndp(struct bcm_cfg80211 *cfg,
- struct net_device *nan_ndev)
- {
- s32 ret = BCME_OK;
- uint8 i = 0;
- for (i = 0; i < NAN_MAX_NDI; i++) {
- if (cfg->nancfg.ndi[i].in_use &&
- cfg->nancfg.ndi[i].created &&
- (cfg->nancfg.ndi[i].nan_ndev == nan_ndev)) {
- WL_INFORM_MEM(("iface name: %s, cfg->nancfg.ndi[i].nan_ndev = %p"
- " and nan_ndev = %p\n",
- (char*)cfg->nancfg.ndi[i].ifname,
- cfg->nancfg.ndi[i].nan_ndev, nan_ndev));
- ret = _wl_cfg80211_del_if(cfg, nan_ndev, NULL,
- (char*)cfg->nancfg.ndi[i].ifname);
- if (ret) {
- WL_ERR(("failed to del ndi [%d]\n", ret));
- goto exit;
- }
- /* After successful delete of interface,
- * clear up the ndi data
- */
- if (wl_cfgnan_del_ndi_data(cfg,
- (char*)cfg->nancfg.ndi[i].ifname) < 0) {
- WL_ERR(("Failed to find matching data for ndi:%s\n",
- (char*)cfg->nancfg.ndi[i].ifname));
- }
- }
- }
- exit:
- return ret;
- }
- #endif /* WL_NAN */
|