| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487 |
- /******************************************************************************
- *
- * Copyright(c) 2007 - 2017 Realtek Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- *****************************************************************************/
- #define _RTW_MLME_EXT_C_
- #include <drv_types.h>
- #ifdef CONFIG_IOCTL_CFG80211
- #include <rtw_wifi_regd.h>
- #endif /* CONFIG_IOCTL_CFG80211 */
- #include <hal_data.h>
- struct mlme_handler mlme_sta_tbl[] = {
- {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
- {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
- {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},
- {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},
- {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},
- {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},
- /*----------------------------------------------------------
- below 2 are reserved
- -----------------------------------------------------------*/
- {0, "DoReserved", &DoReserved},
- {0, "DoReserved", &DoReserved},
- {WIFI_BEACON, "OnBeacon", &OnBeacon},
- {WIFI_ATIM, "OnATIM", &OnAtim},
- {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},
- {WIFI_AUTH, "OnAuth", &OnAuthClient},
- {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},
- {WIFI_ACTION, "OnAction", &OnAction},
- {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction},
- };
- #ifdef _CONFIG_NATIVEAP_MLME_
- struct mlme_handler mlme_ap_tbl[] = {
- {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
- {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
- {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},
- {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},
- {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},
- {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},
- /*----------------------------------------------------------
- below 2 are reserved
- -----------------------------------------------------------*/
- {0, "DoReserved", &DoReserved},
- {0, "DoReserved", &DoReserved},
- {WIFI_BEACON, "OnBeacon", &OnBeacon},
- {WIFI_ATIM, "OnATIM", &OnAtim},
- {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},
- {WIFI_AUTH, "OnAuth", &OnAuth},
- {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},
- {WIFI_ACTION, "OnAction", &OnAction},
- {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction},
- };
- #endif
- struct action_handler OnAction_tbl[] = {
- {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},
- {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
- {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
- {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
- {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
- {RTW_WLAN_CATEGORY_RADIO_MEAS, "ACTION_RADIO_MEAS", &on_action_rm},
- {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &OnAction_ft},
- {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},
- #ifdef CONFIG_IEEE80211W
- {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
- #else
- {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
- #endif /* CONFIG_IEEE80211W */
- #ifdef CONFIG_RTW_WNM
- {RTW_WLAN_CATEGORY_WNM, "ACTION_WNM", &on_action_wnm},
- #endif
- {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
- #ifdef CONFIG_RTW_MESH
- {RTW_WLAN_CATEGORY_MESH, "ACTION_MESH", &on_action_mesh},
- {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &on_action_self_protected},
- #endif
- {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
- {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &OnAction_vht},
- {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
- };
- u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
- /**************************************************
- OUI definitions for the vendor specific IE
- ***************************************************/
- unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
- unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
- unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
- unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
- unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
- unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
- unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
- unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
- unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
- extern unsigned char REALTEK_96B_IE[];
- static void init_channel_list(_adapter *padapter, RT_CHANNEL_INFO *channel_set
- , struct p2p_channels *channel_list)
- {
- struct registry_priv *regsty = adapter_to_regsty(padapter);
- struct p2p_oper_class_map op_class[] = {
- { IEEE80211G, 81, 1, 13, 1, BW20 },
- { IEEE80211G, 82, 14, 14, 1, BW20 },
- #if 0 /* Do not enable HT40 on 2 GHz */
- { IEEE80211G, 83, 1, 9, 1, BW40PLUS },
- { IEEE80211G, 84, 5, 13, 1, BW40MINUS },
- #endif
- { IEEE80211A, 115, 36, 48, 4, BW20 },
- { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
- { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
- { IEEE80211A, 124, 149, 161, 4, BW20 },
- { IEEE80211A, 125, 149, 169, 4, BW20 },
- { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
- { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
- { -1, 0, 0, 0, 0, BW20 }
- };
- int cla, op;
- cla = 0;
- for (op = 0; op_class[op].op_class; op++) {
- u8 ch;
- struct p2p_oper_class_map *o = &op_class[op];
- struct p2p_reg_class *reg = NULL;
- for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
- if (rtw_chset_search_ch(channel_set, ch) == -1)
- continue;
- #if defined(CONFIG_80211N_HT) || defined(CONFIG_80211AC_VHT)
- if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8))
- continue;
- if ((REGSTY_IS_BW_5G_SUPPORT(regsty, CHANNEL_WIDTH_40)) &&
- ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
- continue;
- #endif
- if (reg == NULL) {
- reg = &channel_list->reg_class[cla];
- cla++;
- reg->reg_class = o->op_class;
- reg->channels = 0;
- }
- reg->channel[reg->channels] = ch;
- reg->channels++;
- }
- }
- channel_list->reg_classes = cla;
- }
- #ifdef CONFIG_TXPWR_LIMIT
- void rtw_txpwr_init_regd(struct rf_ctl_t *rfctl)
- {
- u8 regd;
- struct regd_exc_ent *exc;
- struct txpwr_lmt_ent *ent;
- _irqL irqL;
- _enter_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
- rfctl->regd_name = NULL;
- if (rfctl->txpwr_regd_num == 0) {
- RTW_PRINT("there is no any txpwr_regd\n");
- goto release_lock;
- }
- /* search from exception mapping */
- exc = _rtw_regd_exc_search(rfctl
- , rfctl->country_ent ? rfctl->country_ent->alpha2 : NULL
- , rfctl->ChannelPlan);
- if (exc) {
- u8 has_country = (exc->country[0] == '\0' && exc->country[1] == '\0') ? 0 : 1;
- if (strcmp(exc->regd_name, regd_str(TXPWR_LMT_NONE)) == 0)
- rfctl->regd_name = regd_str(TXPWR_LMT_NONE);
- else if (strcmp(exc->regd_name, regd_str(TXPWR_LMT_WW)) == 0)
- rfctl->regd_name = regd_str(TXPWR_LMT_WW);
- else {
- ent = _rtw_txpwr_lmt_get_by_name(rfctl, exc->regd_name);
- if (ent)
- rfctl->regd_name = ent->regd_name;
- }
- RTW_PRINT("exception mapping country:%c%c domain:0x%02x to%s regd_name:%s\n"
- , has_country ? exc->country[0] : '0'
- , has_country ? exc->country[1] : '0'
- , exc->domain
- , rfctl->regd_name ? "" : " unknown"
- , exc->regd_name
- );
- if (rfctl->regd_name)
- goto release_lock;
- }
- /* follow default channel plan mapping */
- regd = rtw_chplan_get_default_regd(rfctl->ChannelPlan);
- if (regd == TXPWR_LMT_NONE)
- rfctl->regd_name = regd_str(TXPWR_LMT_NONE);
- else if (regd == TXPWR_LMT_WW)
- rfctl->regd_name = regd_str(TXPWR_LMT_WW);
- else {
- ent = _rtw_txpwr_lmt_get_by_name(rfctl, regd_str(regd));
- if (ent)
- rfctl->regd_name = ent->regd_name;
- }
- RTW_PRINT("default mapping domain:0x%02x to%s regd_name:%s\n"
- , rfctl->ChannelPlan
- , rfctl->regd_name ? "" : " unknown"
- , regd_str(regd)
- );
- if (rfctl->regd_name)
- goto release_lock;
- switch (regd) {
- /*
- * To support older chips without new predefined regd:
- * - use FCC if IC or CHILE not found
- * - use ETSI if KCC or ACMA not found
- */
- case TXPWR_LMT_IC:
- case TXPWR_LMT_KCC:
- case TXPWR_LMT_ACMA:
- case TXPWR_LMT_CHILE:
- if (regd == TXPWR_LMT_IC || regd == TXPWR_LMT_CHILE)
- regd = TXPWR_LMT_FCC;
- else if (regd == TXPWR_LMT_KCC || regd == TXPWR_LMT_ACMA)
- regd = TXPWR_LMT_ETSI;
- ent = _rtw_txpwr_lmt_get_by_name(rfctl, regd_str(regd));
- if (ent)
- rfctl->regd_name = ent->regd_name;
- RTW_PRINT("alternate regd_name:%s %s\n"
- , regd_str(regd)
- , rfctl->regd_name ? "is used" : "not found"
- );
- if (rfctl->regd_name)
- break;
- default:
- rfctl->regd_name = regd_str(TXPWR_LMT_WW);
- RTW_PRINT("assign %s for default case\n", regd_str(TXPWR_LMT_WW));
- break;
- };
- release_lock:
- _exit_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);
- }
- #endif /* CONFIG_TXPWR_LIMIT */
- void rtw_rfctl_init(_adapter *adapter)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- rfctl->max_chan_nums = init_channel_set(adapter, rfctl->ChannelPlan, rfctl->channel_set);
- init_channel_list(adapter, rfctl->channel_set, &rfctl->channel_list);
- _rtw_mutex_init(&rfctl->offch_mutex);
- #ifdef CONFIG_TXPWR_LIMIT
- _rtw_mutex_init(&rfctl->txpwr_lmt_mutex);
- _rtw_init_listhead(&rfctl->reg_exc_list);
- _rtw_init_listhead(&rfctl->txpwr_lmt_list);
- #endif
- rfctl->ch_sel_same_band_prefer = 1;
- #ifdef CONFIG_DFS_MASTER
- rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;
- rtw_init_timer(&(rfctl->radar_detect_timer), adapter, rtw_dfs_rd_timer_hdl, rfctl);
- #endif
- #ifdef CONFIG_DFS_SLAVE_WITH_RADAR_DETECT
- rfctl->dfs_slave_with_rd = 1;
- #endif
- }
- void rtw_rfctl_deinit(_adapter *adapter)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- _rtw_mutex_free(&rfctl->offch_mutex);
- #ifdef CONFIG_TXPWR_LIMIT
- rtw_regd_exc_list_free(rfctl);
- rtw_txpwr_lmt_list_free(rfctl);
- _rtw_mutex_free(&rfctl->txpwr_lmt_mutex);
- #endif
- }
- #ifdef CONFIG_DFS_MASTER
- /*
- * called in rtw_dfs_rd_enable()
- * assume the request channel coverage is DFS range
- * base on the current status and the request channel coverage to check if need to reset complete CAC time
- */
- bool rtw_is_cac_reset_needed(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset)
- {
- bool needed = _FALSE;
- u32 cur_hi, cur_lo, hi, lo;
- if (rfctl->radar_detected == 1) {
- needed = _TRUE;
- goto exit;
- }
- if (rfctl->radar_detect_ch == 0) {
- needed = _TRUE;
- goto exit;
- }
- if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) {
- RTW_ERR("request detection range ch:%u, bw:%u, offset:%u\n", ch, bw, offset);
- rtw_warn_on(1);
- }
- if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset, &cur_hi, &cur_lo) == _FALSE) {
- RTW_ERR("cur detection range ch:%u, bw:%u, offset:%u\n", rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
- rtw_warn_on(1);
- }
- if (hi <= lo || cur_hi <= cur_lo) {
- RTW_ERR("hi:%u, lo:%u, cur_hi:%u, cur_lo:%u\n", hi, lo, cur_hi, cur_lo);
- rtw_warn_on(1);
- }
- if (rtw_is_range_a_in_b(hi, lo, cur_hi, cur_lo)) {
- /* request is in current detect range */
- goto exit;
- }
- /* check if request channel coverage has new range and the new range is in DFS range */
- if (!rtw_is_range_overlap(hi, lo, cur_hi, cur_lo)) {
- /* request has no overlap with current */
- needed = _TRUE;
- } else if (rtw_is_range_a_in_b(cur_hi, cur_lo, hi, lo)) {
- /* request is supper set of current */
- if ((hi != cur_hi && rtw_is_dfs_range(hi, cur_hi)) || (lo != cur_lo && rtw_is_dfs_range(cur_lo, lo)))
- needed = _TRUE;
- } else {
- /* request is not supper set of current, but has overlap */
- if ((lo < cur_lo && rtw_is_dfs_range(cur_lo, lo)) || (hi > cur_hi && rtw_is_dfs_range(hi, cur_hi)))
- needed = _TRUE;
- }
- exit:
- return needed;
- }
- bool _rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset)
- {
- bool ret = _FALSE;
- u32 hi = 0, lo = 0;
- u32 r_hi = 0, r_lo = 0;
- int i;
- if (rfctl->radar_detect_by_others)
- goto exit;
- if (rfctl->radar_detect_ch == 0)
- goto exit;
- if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) {
- rtw_warn_on(1);
- goto exit;
- }
- if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch
- , rfctl->radar_detect_bw, rfctl->radar_detect_offset
- , &r_hi, &r_lo) == _FALSE) {
- rtw_warn_on(1);
- goto exit;
- }
- if (rtw_is_range_overlap(hi, lo, r_hi, r_lo))
- ret = _TRUE;
- exit:
- return ret;
- }
- bool rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl)
- {
- return _rtw_rfctl_overlap_radar_detect_ch(rfctl
- , rfctl_to_dvobj(rfctl)->oper_channel
- , rfctl_to_dvobj(rfctl)->oper_bwmode
- , rfctl_to_dvobj(rfctl)->oper_ch_offset);
- }
- bool rtw_rfctl_is_tx_blocked_by_ch_waiting(struct rf_ctl_t *rfctl)
- {
- return rtw_rfctl_overlap_radar_detect_ch(rfctl) && IS_CH_WAITING(rfctl);
- }
- bool rtw_chset_is_chbw_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)
- {
- bool ret = _FALSE;
- u32 hi = 0, lo = 0;
- int i;
- if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
- goto exit;
- for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {
- if (!rtw_ch2freq(ch_set[i].ChannelNum)) {
- rtw_warn_on(1);
- continue;
- }
- if (!CH_IS_NON_OCP(&ch_set[i]))
- continue;
- if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)
- && rtw_ch2freq(ch_set[i].ChannelNum) <= hi
- ) {
- ret = _TRUE;
- break;
- }
- }
- exit:
- return ret;
- }
- bool rtw_chset_is_ch_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch)
- {
- return rtw_chset_is_chbw_non_ocp(ch_set, ch, CHANNEL_WIDTH_20, HAL_PRIME_CHNL_OFFSET_DONT_CARE);
- }
- u32 rtw_chset_get_ch_non_ocp_ms(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)
- {
- int ms = 0;
- systime current_time;
- u32 hi = 0, lo = 0;
- int i;
- if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
- goto exit;
- current_time = rtw_get_current_time();
- for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {
- if (!rtw_ch2freq(ch_set[i].ChannelNum)) {
- rtw_warn_on(1);
- continue;
- }
- if (!CH_IS_NON_OCP(&ch_set[i]))
- continue;
- if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)
- && rtw_ch2freq(ch_set[i].ChannelNum) <= hi
- ) {
- if (rtw_systime_to_ms(ch_set[i].non_ocp_end_time - current_time) > ms)
- ms = rtw_systime_to_ms(ch_set[i].non_ocp_end_time - current_time);
- }
- }
- exit:
- return ms;
- }
- /**
- * rtw_chset_update_non_ocp - update non_ocp_end_time according to the given @ch, @bw, @offset into @ch_set
- * @ch_set: the given channel set
- * @ch: channel number on which radar is detected
- * @bw: bandwidth on which radar is detected
- * @offset: bandwidth offset on which radar is detected
- * @ms: ms to add from now to update non_ocp_end_time, ms < 0 means use NON_OCP_TIME_MS
- */
- static void _rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms)
- {
- u32 hi = 0, lo = 0;
- int i;
- if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
- goto exit;
- for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {
- if (!rtw_ch2freq(ch_set[i].ChannelNum)) {
- rtw_warn_on(1);
- continue;
- }
- if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)
- && rtw_ch2freq(ch_set[i].ChannelNum) <= hi
- ) {
- if (ms >= 0)
- ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(ms);
- else
- ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(NON_OCP_TIME_MS);
- }
- }
- exit:
- return;
- }
- inline void rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)
- {
- _rtw_chset_update_non_ocp(ch_set, ch, bw, offset, -1);
- }
- inline void rtw_chset_update_non_ocp_ms(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms)
- {
- _rtw_chset_update_non_ocp(ch_set, ch, bw, offset, ms);
- }
- u32 rtw_get_ch_waiting_ms(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, u32 *r_non_ocp_ms, u32 *r_cac_ms)
- {
- struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
- u32 non_ocp_ms;
- u32 cac_ms;
- u8 in_rd_range = 0; /* if in current radar detection range*/
- if (rtw_chset_is_chbw_non_ocp(rfctl->channel_set, ch, bw, offset))
- non_ocp_ms = rtw_chset_get_ch_non_ocp_ms(rfctl->channel_set, ch, bw, offset);
- else
- non_ocp_ms = 0;
- if (rfctl->radar_detect_enabled) {
- u32 cur_hi, cur_lo, hi, lo;
- if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) {
- RTW_ERR("input range ch:%u, bw:%u, offset:%u\n", ch, bw, offset);
- rtw_warn_on(1);
- }
- if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset, &cur_hi, &cur_lo) == _FALSE) {
- RTW_ERR("cur detection range ch:%u, bw:%u, offset:%u\n", rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
- rtw_warn_on(1);
- }
- if (rtw_is_range_a_in_b(hi, lo, cur_hi, cur_lo))
- in_rd_range = 1;
- }
- if (!rtw_is_dfs_chbw(ch, bw, offset))
- cac_ms = 0;
- else if (in_rd_range && !non_ocp_ms) {
- if (IS_CH_WAITING(rfctl))
- cac_ms = rtw_systime_to_ms(rfctl->cac_end_time - rtw_get_current_time());
- else
- cac_ms = 0;
- } else if (rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj)))
- cac_ms = CAC_TIME_CE_MS;
- else
- cac_ms = CAC_TIME_MS;
- if (r_non_ocp_ms)
- *r_non_ocp_ms = non_ocp_ms;
- if (r_cac_ms)
- *r_cac_ms = cac_ms;
- return non_ocp_ms + cac_ms;
- }
- void rtw_reset_cac(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset)
- {
- u32 non_ocp_ms;
- u32 cac_ms;
- rtw_get_ch_waiting_ms(rfctl
- , ch
- , bw
- , offset
- , &non_ocp_ms
- , &cac_ms
- );
- rfctl->cac_start_time = rtw_get_current_time() + rtw_ms_to_systime(non_ocp_ms);
- rfctl->cac_end_time = rfctl->cac_start_time + rtw_ms_to_systime(cac_ms);
- /* skip special value */
- if (rfctl->cac_start_time == RTW_CAC_STOPPED) {
- rfctl->cac_start_time++;
- rfctl->cac_end_time++;
- }
- if (rfctl->cac_end_time == RTW_CAC_STOPPED)
- rfctl->cac_end_time++;
- }
- u32 rtw_force_stop_cac(struct rf_ctl_t *rfctl, u32 timeout_ms)
- {
- struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
- systime start;
- u32 pass_ms;
- start = rtw_get_current_time();
- rfctl->cac_force_stop = 1;
- while (rtw_get_passing_time_ms(start) <= timeout_ms
- && IS_UNDER_CAC(rfctl)
- ) {
- if (dev_is_surprise_removed(dvobj) || dev_is_drv_stopped(dvobj))
- break;
- rtw_msleep_os(20);
- }
- if (IS_UNDER_CAC(rfctl)) {
- if (!dev_is_surprise_removed(dvobj) && !dev_is_drv_stopped(dvobj))
- RTW_INFO("%s waiting for cac stop timeout!\n", __func__);
- }
- rfctl->cac_force_stop = 0;
- pass_ms = rtw_get_passing_time_ms(start);
- return pass_ms;
- }
- #endif /* CONFIG_DFS_MASTER */
- /* choose channel with shortest waiting (non ocp + cac) time */
- bool rtw_choose_shortest_waiting_ch(struct rf_ctl_t *rfctl, u8 sel_ch, u8 max_bw
- , u8 *dec_ch, u8 *dec_bw, u8 *dec_offset
- , u8 d_flags, u8 cur_ch, u8 same_band_prefer, u8 mesh_only)
- {
- #ifndef DBG_CHOOSE_SHORTEST_WAITING_CH
- #define DBG_CHOOSE_SHORTEST_WAITING_CH 0
- #endif
- struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
- struct registry_priv *regsty = dvobj_to_regsty(dvobj);
- u8 ch, bw, offset;
- u8 ch_c = 0, bw_c = 0, offset_c = 0;
- int i;
- u32 min_waiting_ms = 0;
- if (!dec_ch || !dec_bw || !dec_offset) {
- rtw_warn_on(1);
- return _FALSE;
- }
- /* full search and narrow bw judegement first to avoid potetial judegement timing issue */
- for (bw = CHANNEL_WIDTH_20; bw <= max_bw; bw++) {
- if (!hal_is_bw_support(dvobj_get_primary_adapter(dvobj), bw))
- continue;
- for (i = 0; i < rfctl->max_chan_nums; i++) {
- u32 non_ocp_ms = 0;
- u32 cac_ms = 0;
- u32 waiting_ms = 0;
- ch = rfctl->channel_set[i].ChannelNum;
- if (sel_ch > 0 && ch != sel_ch)
- continue;
- if ((d_flags & RTW_CHF_2G) && ch <= 14)
- continue;
- if ((d_flags & RTW_CHF_5G) && ch > 14)
- continue;
- if (ch > 14) {
- if (bw > REGSTY_BW_5G(regsty))
- continue;
- } else {
- if (bw > REGSTY_BW_2G(regsty))
- continue;
- }
- if (mesh_only && ch >= 5 && ch <= 9 && bw > CHANNEL_WIDTH_20)
- continue;
- if (!rtw_get_offset_by_chbw(ch, bw, &offset))
- continue;
- if (!rtw_chset_is_chbw_valid(rfctl->channel_set, ch, bw, offset))
- continue;
- if ((d_flags & RTW_CHF_NON_OCP) && rtw_chset_is_chbw_non_ocp(rfctl->channel_set, ch, bw, offset))
- continue;
- if ((d_flags & RTW_CHF_DFS) && rtw_is_dfs_chbw(ch, bw, offset))
- continue;
- if ((d_flags & RTW_CHF_LONG_CAC) && rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj)))
- continue;
- if ((d_flags & RTW_CHF_NON_DFS) && !rtw_is_dfs_chbw(ch, bw, offset))
- continue;
- if ((d_flags & RTW_CHF_NON_LONG_CAC) && !rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj)))
- continue;
- #ifdef CONFIG_DFS_MASTER
- waiting_ms = rtw_get_ch_waiting_ms(rfctl, ch, bw, offset, &non_ocp_ms, &cac_ms);
- #endif
- if (DBG_CHOOSE_SHORTEST_WAITING_CH)
- RTW_INFO("%s:%u,%u,%u %u(non_ocp:%u, cac:%u)\n"
- , __func__, ch, bw, offset, waiting_ms, non_ocp_ms, cac_ms);
- if (ch_c == 0
- /* first: smaller wating time */
- || min_waiting_ms > waiting_ms
- /* then: wider bw */
- || (min_waiting_ms == waiting_ms && bw > bw_c)
- /* then: same band if requested */
- || (same_band_prefer && min_waiting_ms == waiting_ms && bw == bw_c
- && !rtw_is_same_band(cur_ch, ch_c) && rtw_is_same_band(cur_ch, ch))
- ) {
- ch_c = ch;
- bw_c = bw;
- offset_c = offset;
- min_waiting_ms = waiting_ms;
- }
- }
- }
- if (ch_c != 0) {
- RTW_INFO("%s: d_flags:0x%02x cur_ch:%u sb_prefer:%u%s %u,%u,%u waiting_ms:%u\n"
- , __func__, d_flags, cur_ch, same_band_prefer
- , mesh_only ? " mesh_only" : ""
- , ch_c, bw_c, offset_c, min_waiting_ms);
- *dec_ch = ch_c;
- *dec_bw = bw_c;
- *dec_offset = offset_c;
- return _TRUE;
- }
- if (d_flags == 0) {
- RTW_INFO("%s: sel_ch:%u max_bw:%u d_flags:0x%02x cur_ch:%u sb_prefer:%u%s\n"
- , __func__, sel_ch, max_bw, d_flags, cur_ch, same_band_prefer
- , mesh_only ? " mesh_only" : "");
- rtw_warn_on(1);
- }
- return _FALSE;
- }
- void dump_chset(void *sel, RT_CHANNEL_INFO *ch_set)
- {
- u8 i;
- for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {
- RTW_PRINT_SEL(sel, "ch:%3u, freq:%u, scan_type:%d"
- , ch_set[i].ChannelNum, rtw_ch2freq(ch_set[i].ChannelNum), ch_set[i].ScanType);
- #ifdef CONFIG_FIND_BEST_CHANNEL
- _RTW_PRINT_SEL(sel, ", rx_count:%u", ch_set[i].rx_count);
- #endif
- #ifdef CONFIG_DFS_MASTER
- if (rtw_is_dfs_ch(ch_set[i].ChannelNum)) {
- if (CH_IS_NON_OCP(&ch_set[i]))
- _RTW_PRINT_SEL(sel, ", non_ocp:%d"
- , rtw_systime_to_ms(ch_set[i].non_ocp_end_time - rtw_get_current_time()));
- else
- _RTW_PRINT_SEL(sel, ", non_ocp:N/A");
- }
- #endif
- _RTW_PRINT_SEL(sel, "\n");
- }
- RTW_PRINT_SEL(sel, "total ch number:%d\n", i);
- }
- void dump_cur_chset(void *sel, struct rf_ctl_t *rfctl)
- {
- struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);
- struct registry_priv *regsty = dvobj_to_regsty(dvobj);
- int i;
- if (rfctl->country_ent)
- dump_country_chplan(sel, rfctl->country_ent);
- else
- RTW_PRINT_SEL(sel, "chplan:0x%02X\n", rfctl->ChannelPlan);
- #ifdef CONFIG_TXPWR_LIMIT
- RTW_PRINT_SEL(sel, "PLS regd:%s\n", rfctl->regd_name);
- #endif
- #ifdef CONFIG_DFS_MASTER
- RTW_PRINT_SEL(sel, "dfs_domain:%u\n", rtw_odm_get_dfs_domain(dvobj));
- #endif
- for (i = 0; i < MAX_CHANNEL_NUM; i++)
- if (regsty->excl_chs[i] != 0)
- break;
- if (i < MAX_CHANNEL_NUM) {
- RTW_PRINT_SEL(sel, "excl_chs:");
- for (i = 0; i < MAX_CHANNEL_NUM; i++) {
- if (regsty->excl_chs[i] == 0)
- break;
- _RTW_PRINT_SEL(sel, "%u ", regsty->excl_chs[i]);
- }
- _RTW_PRINT_SEL(sel, "\n");
- }
- dump_chset(sel, rfctl->channel_set);
- }
- /*
- * Search the @param ch in given @param ch_set
- * @ch_set: the given channel set
- * @ch: the given channel number
- *
- * return the index of channel_num in channel_set, -1 if not found
- */
- int rtw_chset_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)
- {
- int i;
- if (ch == 0)
- return -1;
- for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {
- if (ch == ch_set[i].ChannelNum)
- return i;
- }
- return -1;
- }
- /*
- * Check if the @param ch, bw, offset is valid for the given @param ch_set
- * @ch_set: the given channel set
- * @ch: the given channel number
- * @bw: the given bandwidth
- * @offset: the given channel offset
- *
- * return valid (1) or not (0)
- */
- u8 rtw_chset_is_chbw_valid(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)
- {
- u8 cch;
- u8 *op_chs;
- u8 op_ch_num;
- u8 valid = 0;
- int i;
- cch = rtw_get_center_ch(ch, bw, offset);
- if (!rtw_get_op_chs_by_cch_bw(cch, bw, &op_chs, &op_ch_num))
- goto exit;
- for (i = 0; i < op_ch_num; i++) {
- if (0)
- RTW_INFO("%u,%u,%u - cch:%u, bw:%u, op_ch:%u\n", ch, bw, offset, cch, bw, *(op_chs + i));
- if (rtw_chset_search_ch(ch_set, *(op_chs + i)) == -1)
- break;
- }
- if (op_ch_num != 0 && i == op_ch_num)
- valid = 1;
- exit:
- return valid;
- }
- /**
- * rtw_chset_sync_chbw - obey g_ch, adjust g_bw, g_offset, bw, offset to fit in channel plan
- * @ch_set: channel plan to check
- * @req_ch: pointer of the request ch, may be modified further
- * @req_bw: pointer of the request bw, may be modified further
- * @req_offset: pointer of the request offset, may be modified further
- * @g_ch: pointer of the ongoing group ch
- * @g_bw: pointer of the ongoing group bw, may be modified further
- * @g_offset: pointer of the ongoing group offset, may be modified further
- */
- void rtw_chset_sync_chbw(RT_CHANNEL_INFO *ch_set, u8 *req_ch, u8 *req_bw, u8 *req_offset
- , u8 *g_ch, u8 *g_bw, u8 *g_offset)
- {
- u8 r_ch, r_bw, r_offset;
- u8 u_ch, u_bw, u_offset;
- u8 cur_bw = *req_bw;
- while (1) {
- r_ch = *req_ch;
- r_bw = cur_bw;
- r_offset = *req_offset;
- u_ch = *g_ch;
- u_bw = *g_bw;
- u_offset = *g_offset;
- rtw_sync_chbw(&r_ch, &r_bw, &r_offset, &u_ch, &u_bw, &u_offset);
- if (rtw_chset_is_chbw_valid(ch_set, r_ch, r_bw, r_offset))
- break;
- if (cur_bw == CHANNEL_WIDTH_20) {
- rtw_warn_on(1);
- break;
- }
- cur_bw--;
- };
- *req_ch = r_ch;
- *req_bw = r_bw;
- *req_offset = r_offset;
- *g_ch = u_ch;
- *g_bw = u_bw;
- *g_offset = u_offset;
- }
- /*
- * Check the @param ch is fit with setband setting of @param adapter
- * @adapter: the given adapter
- * @ch: the given channel number
- *
- * return _TRUE when check valid, _FALSE not valid
- */
- bool rtw_mlme_band_check(_adapter *adapter, const u32 ch)
- {
- if (adapter->setband == WIFI_FREQUENCY_BAND_AUTO /* 2.4G and 5G */
- || (adapter->setband == WIFI_FREQUENCY_BAND_2GHZ && ch < 35) /* 2.4G only */
- || (adapter->setband == WIFI_FREQUENCY_BAND_5GHZ && ch > 35) /* 5G only */
- )
- return _TRUE;
- return _FALSE;
- }
- inline void RTW_SET_SCAN_BAND_SKIP(_adapter *padapter, int skip_band)
- {
- int bs = ATOMIC_READ(&padapter->bandskip);
- bs |= skip_band;
- ATOMIC_SET(&padapter->bandskip, bs);
- }
- inline void RTW_CLR_SCAN_BAND_SKIP(_adapter *padapter, int skip_band)
- {
- int bs = ATOMIC_READ(&padapter->bandskip);
- bs &= ~(skip_band);
- ATOMIC_SET(&padapter->bandskip, bs);
- }
- inline int RTW_GET_SCAN_BAND_SKIP(_adapter *padapter)
- {
- return ATOMIC_READ(&padapter->bandskip);
- }
- #define RTW_IS_SCAN_BAND_SKIP(padapter, skip_band) (ATOMIC_READ(&padapter->bandskip) & (skip_band))
- bool rtw_mlme_ignore_chan(_adapter *adapter, const u32 ch)
- {
- if (RTW_IS_SCAN_BAND_SKIP(adapter, BAND_24G) && ch < 35) /* SKIP 2.4G Band channel */
- return _TRUE;
- if (RTW_IS_SCAN_BAND_SKIP(adapter, BAND_5G) && ch > 35) /* SKIP 5G Band channel */
- return _TRUE;
- return _FALSE;
- }
- /****************************************************************************
- Following are the initialization functions for WiFi MLME
- *****************************************************************************/
- int init_hw_mlme_ext(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
- u8 rx_bar_enble = _TRUE;
- /*
- * Sync driver status and hardware setting
- */
- /* Modify to make sure first time change channel(band) would be done properly */
- pHalData->current_channel = 0;
- pHalData->current_channel_bw = CHANNEL_WIDTH_MAX;
- pHalData->current_band_type = BAND_MAX;
- /* set_opmode_cmd(padapter, infra_client_with_mlme); */ /* removed */
- rtw_hal_set_hwreg(padapter, HW_VAR_ENABLE_RX_BAR, &rx_bar_enble);
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
- return _SUCCESS;
- }
- void init_mlme_default_rate_set(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- unsigned char end_set[1] = {0xff};
- u8 offset_datarate = 0;
- u8 offset_basicrate = 0;
- #ifdef CONFIG_80211N_HT
- unsigned char supported_mcs_set[16] = {0xff, 0xff, 0xff, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
- #endif
- if (IsSupportedTxCCK(padapter->registrypriv.wireless_mode)) {
- unsigned char datarate_b[B_MODE_RATE_NUM] ={_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_};
- _rtw_memcpy(pmlmeext->datarate, datarate_b, B_MODE_RATE_NUM);
- _rtw_memcpy(pmlmeext->basicrate, datarate_b, B_MODE_RATE_NUM);
- offset_datarate += B_MODE_RATE_NUM;
- offset_basicrate += B_MODE_RATE_NUM;
- RTW_INFO("%s: support CCK\n", __func__);
- }
- if(IsSupportedTxOFDM(padapter->registrypriv.wireless_mode)) {
- unsigned char datarate_g[G_MODE_RATE_NUM] ={_6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_,_24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_};
- unsigned char basicrate_g[G_MODE_BASIC_RATE_NUM] = {_6M_RATE_, _12M_RATE_, _24M_RATE_};
- _rtw_memcpy(pmlmeext->datarate + offset_datarate, datarate_g, G_MODE_RATE_NUM);
- _rtw_memcpy(pmlmeext->basicrate + offset_basicrate,basicrate_g, G_MODE_BASIC_RATE_NUM);
- offset_datarate += G_MODE_RATE_NUM;
- offset_basicrate += G_MODE_BASIC_RATE_NUM;
- RTW_INFO("%s: support OFDM\n", __func__);
- }
- _rtw_memcpy(pmlmeext->datarate + offset_datarate, end_set, 1);
- _rtw_memcpy(pmlmeext->basicrate + offset_basicrate, end_set, 1);
- #ifdef CONFIG_80211N_HT
- if( padapter->registrypriv.ht_enable && is_supported_ht(padapter->registrypriv.wireless_mode))
- _rtw_memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
- #endif
- }
- static void init_mlme_ext_priv_value(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- ATOMIC_SET(&pmlmeext->event_seq, 0);
- pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
- #ifdef CONFIG_IEEE80211W
- pmlmeext->sa_query_seq = 0;
- #endif
- pmlmeext->cur_channel = padapter->registrypriv.channel;
- pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pmlmeext->retry = 0;
- pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
- init_mlme_default_rate_set(padapter);
- if (pmlmeext->cur_channel > 14)
- pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
- else
- pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
- mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
- pmlmeext->sitesurvey_res.channel_idx = 0;
- pmlmeext->sitesurvey_res.bss_cnt = 0;
- pmlmeext->sitesurvey_res.scan_ch_ms = SURVEY_TO;
- pmlmeext->sitesurvey_res.rx_ampdu_accept = RX_AMPDU_ACCEPT_INVALID;
- pmlmeext->sitesurvey_res.rx_ampdu_size = RX_AMPDU_SIZE_INVALID;
- #ifdef CONFIG_SCAN_BACKOP
- mlmeext_assign_scan_backop_flags_sta(pmlmeext, /*SS_BACKOP_EN|*/SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME);
- #ifdef CONFIG_AP_MODE
- mlmeext_assign_scan_backop_flags_ap(pmlmeext, SS_BACKOP_EN | SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME);
- #endif
- #ifdef CONFIG_RTW_MESH
- mlmeext_assign_scan_backop_flags_mesh(pmlmeext, /*SS_BACKOP_EN | */SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME);
- #endif
- pmlmeext->sitesurvey_res.scan_cnt = 0;
- pmlmeext->sitesurvey_res.scan_cnt_max = RTW_SCAN_NUM_OF_CH;
- pmlmeext->sitesurvey_res.backop_ms = RTW_BACK_OP_CH_MS;
- #endif
- #if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
- pmlmeext->sitesurvey_res.is_sw_antdiv_bl_scan = 0;
- #endif
- pmlmeext->scan_abort = _FALSE;
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- pmlmeinfo->reauth_count = 0;
- pmlmeinfo->reassoc_count = 0;
- pmlmeinfo->link_count = 0;
- pmlmeinfo->auth_seq = 0;
- pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
- pmlmeinfo->key_index = 0;
- pmlmeinfo->iv = 0;
- pmlmeinfo->enc_algo = _NO_PRIVACY_;
- pmlmeinfo->authModeToggle = 0;
- _rtw_memset(pmlmeinfo->chg_txt, 0, 128);
- pmlmeinfo->slotTime = SHORT_SLOT_TIME;
- pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
- pmlmeinfo->dialogToken = 0;
- pmlmeext->action_public_rxseq = 0xffff;
- pmlmeext->action_public_dialog_token = 0xff;
- #ifdef ROKU_PRIVATE
- /*infra mode, used to store AP's info*/
- _rtw_memset(pmlmeinfo->SupportedRates_infra_ap, 0, NDIS_802_11_LENGTH_RATES_EX);
- pmlmeinfo->ht_vht_received = 0;
- #endif /* ROKU_PRIVATE */
- }
- void init_mlme_ext_timer(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- rtw_init_timer(&pmlmeext->survey_timer, padapter, survey_timer_hdl, padapter);
- rtw_init_timer(&pmlmeext->link_timer, padapter, link_timer_hdl, padapter);
- #ifdef CONFIG_RTW_80211R
- rtw_init_timer(&pmlmeext->ft_link_timer, padapter, rtw_ft_link_timer_hdl, padapter);
- rtw_init_timer(&pmlmeext->ft_roam_timer, padapter, rtw_ft_roam_timer_hdl, padapter);
- #endif
- #ifdef CONFIG_RTW_REPEATER_SON
- rtw_init_timer(&pmlmeext->rson_scan_timer, padapter, rson_timer_hdl, padapter);
- #endif
- }
- int init_mlme_ext_priv(_adapter *padapter)
- {
- int res = _SUCCESS;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- /* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */
- /* _rtw_memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv)); */
- pmlmeext->padapter = padapter;
- /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
- init_mlme_ext_priv_value(padapter);
- pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
- init_mlme_ext_timer(padapter);
- #ifdef CONFIG_AP_MODE
- init_mlme_ap_info(padapter);
- #endif
- pmlmeext->last_scan_time = 0;
- pmlmeext->mlmeext_init = _TRUE;
- #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
- pmlmeext->active_keep_alive_check = _TRUE;
- #else
- pmlmeext->active_keep_alive_check = _FALSE;
- #endif
- #ifdef DBG_FIXED_CHAN
- pmlmeext->fixed_chan = 0xFF;
- #endif
- pmlmeext->tsf_update_pause_factor = pregistrypriv->tsf_update_pause_factor;
- pmlmeext->tsf_update_restore_factor = pregistrypriv->tsf_update_restore_factor;
- return res;
- }
- void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
- {
- _adapter *padapter = pmlmeext->padapter;
- if (!padapter)
- return;
- if (rtw_is_drv_stopped(padapter)) {
- _cancel_timer_ex(&pmlmeext->survey_timer);
- _cancel_timer_ex(&pmlmeext->link_timer);
- }
- }
- #ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL
- static u8 cmp_pkt_chnl_diff(_adapter *padapter, u8 *pframe, uint packet_len)
- {
- /* if the channel is same, return 0. else return channel differential */
- uint len;
- u8 channel;
- u8 *p;
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, packet_len - _BEACON_IE_OFFSET_);
- if (p) {
- channel = *(p + 2);
- if (padapter->mlmeextpriv.cur_channel >= channel)
- return padapter->mlmeextpriv.cur_channel - channel;
- else
- return channel - padapter->mlmeextpriv.cur_channel;
- } else
- return 0;
- }
- #endif /* CONFIG_PATCH_JOIN_WRONG_CHANNEL */
- static void _mgt_dispatcher(_adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
- {
- u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u8 *pframe = precv_frame->u.hdr.rx_data;
- if (ptable->func) {
- /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
- if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) &&
- !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- {
- struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
- if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) != _TRUE)
- return;
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE)
- return;
- if ( pwdev_priv->pno_mac_addr[0] == 0xFF)
- return;
- if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_pno_mac_addr(padapter), ETH_ALEN))
- return;
- }
- #else
- return;
- #endif
- ptable->func(padapter, precv_frame);
- }
- }
- void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame)
- {
- int index;
- struct mlme_handler *ptable;
- u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u8 *pframe = precv_frame->u.hdr.rx_data;
- struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, get_addr2_ptr(pframe));
- struct recv_priv *precvpriv = &padapter->recvpriv;
- #if 0
- {
- u8 *pbuf;
- pbuf = GetAddr1Ptr(pframe);
- RTW_INFO("A1-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5));
- pbuf = get_addr2_ptr(pframe);
- RTW_INFO("A2-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5));
- pbuf = GetAddr3Ptr(pframe);
- RTW_INFO("A3-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5));
- }
- #endif
- if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
- return;
- }
- /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
- if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) &&
- !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- {
- struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
- if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) != _TRUE)
- return;
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE)
- return;
- if ( pwdev_priv->pno_mac_addr[0] == 0xFF)
- return;
- if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_pno_mac_addr(padapter), ETH_ALEN))
- return;
- }
- #else
- return;
- #endif
- ptable = mlme_sta_tbl;
- index = get_frame_sub_type(pframe) >> 4;
- #ifdef CONFIG_TDLS
- if ((index << 4) == WIFI_ACTION) {
- /* category==public (4), action==TDLS_DISCOVERY_RESPONSE */
- if (*(pframe + 24) == RTW_WLAN_CATEGORY_PUBLIC && *(pframe + 25) == TDLS_DISCOVERY_RESPONSE) {
- RTW_INFO("[TDLS] Recv %s from "MAC_FMT"\n", rtw_tdls_action_txt(TDLS_DISCOVERY_RESPONSE), MAC_ARG(get_addr2_ptr(pframe)));
- On_TDLS_Dis_Rsp(padapter, precv_frame);
- }
- }
- #endif /* CONFIG_TDLS */
- if (index >= (sizeof(mlme_sta_tbl) / sizeof(struct mlme_handler))) {
- return;
- }
- ptable += index;
- #if 1
- if (psta != NULL) {
- if (GetRetry(pframe)) {
- if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
- /* drop the duplicate management frame */
- precvpriv->dbg_rx_dup_mgt_frame_drop_count++;
- RTW_INFO("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);
- return;
- }
- }
- psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
- }
- #else
- if (GetRetry(pframe)) {
- /* return; */
- }
- #endif
- #ifdef CONFIG_AP_MODE
- switch (get_frame_sub_type(pframe)) {
- case WIFI_AUTH:
- if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter))
- ptable->func = &OnAuth;
- else
- ptable->func = &OnAuthClient;
- /* pass through */
- case WIFI_ASSOCREQ:
- case WIFI_REASSOCREQ:
- _mgt_dispatcher(padapter, ptable, precv_frame);
- #ifdef CONFIG_HOSTAPD_MLME
- if (MLME_IS_AP(padapter))
- rtw_hostapd_mlme_rx(padapter, precv_frame);
- #endif
- break;
- case WIFI_PROBEREQ:
- _mgt_dispatcher(padapter, ptable, precv_frame);
- #ifdef CONFIG_HOSTAPD_MLME
- if (MLME_IS_AP(padapter))
- rtw_hostapd_mlme_rx(padapter, precv_frame);
- #endif
- break;
- case WIFI_BEACON:
- _mgt_dispatcher(padapter, ptable, precv_frame);
- break;
- case WIFI_ACTION:
- _mgt_dispatcher(padapter, ptable, precv_frame);
- break;
- default:
- _mgt_dispatcher(padapter, ptable, precv_frame);
- #ifdef CONFIG_HOSTAPD_MLME
- if (MLME_IS_AP(padapter))
- rtw_hostapd_mlme_rx(padapter, precv_frame);
- #endif
- break;
- }
- #else
- _mgt_dispatcher(padapter, ptable, precv_frame);
- #endif
- }
- #ifdef CONFIG_P2P
- u32 p2p_listen_state_process(_adapter *padapter, unsigned char *da)
- {
- bool response = _TRUE;
- #ifdef CONFIG_IOCTL_CFG80211
- if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
- if (rtw_cfg80211_get_is_roch(padapter) == _FALSE
- || rtw_get_oper_ch(padapter) != padapter->wdinfo.listen_channel
- || adapter_wdev_data(padapter)->p2p_enabled == _FALSE
- || padapter->mlmepriv.wps_probe_resp_ie == NULL
- || padapter->mlmepriv.p2p_probe_resp_ie == NULL
- ) {
- #ifdef CONFIG_DEBUG_CFG80211
- RTW_INFO(ADPT_FMT" DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n"
- , ADPT_ARG(padapter)
- , adapter_wdev_data(padapter)->p2p_enabled
- , padapter->mlmepriv.wps_probe_resp_ie
- , padapter->mlmepriv.p2p_probe_resp_ie);
- RTW_INFO(ADPT_FMT" DON'T issue_probersp_p2p: is_ro_ch:%d, op_ch:%d, p2p_listen_channel:%d\n"
- , ADPT_ARG(padapter)
- , rtw_cfg80211_get_is_roch(padapter)
- , rtw_get_oper_ch(padapter)
- , padapter->wdinfo.listen_channel);
- #endif
- response = _FALSE;
- }
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- if (padapter->wdinfo.driver_interface == DRIVER_WEXT) {
- /* do nothing if the device name is empty */
- if (!padapter->wdinfo.device_name_len)
- response = _FALSE;
- }
- if (response == _TRUE)
- issue_probersp_p2p(padapter, da);
- return _SUCCESS;
- }
- #endif /* CONFIG_P2P */
- /****************************************************************************
- Following are the callback functions for each subtype of the management frames
- *****************************************************************************/
- unsigned int OnProbeReq(_adapter *padapter, union recv_frame *precv_frame)
- {
- unsigned int ielen;
- unsigned char *p;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *cur = &(pmlmeinfo->network);
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint len = precv_frame->u.hdr.len;
- u8 is_valid_p2p_probereq = _FALSE;
- #ifdef CONFIG_ATMEL_RC_PATCH
- u8 *target_ie = NULL, *wps_ie = NULL;
- u8 *start;
- uint search_len = 0, wps_ielen = 0, target_ielen = 0;
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- #endif
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- u8 wifi_test_chk_rate = 1;
- #ifdef CONFIG_IOCTL_CFG80211
- if ((pwdinfo->driver_interface == DRIVER_CFG80211)
- && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
- && (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_PROBE_REQ) == _TRUE)
- ) {
- rtw_cfg80211_rx_probe_request(padapter, precv_frame);
- return _SUCCESS;
- }
- #endif /* CONFIG_IOCTL_CFG80211 */
- if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
- !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
- !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
- !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
- !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
- ) {
- /* Commented by Albert 2011/03/17 */
- /* mcs_rate = 0->CCK 1M rate */
- /* mcs_rate = 1->CCK 2M rate */
- /* mcs_rate = 2->CCK 5.5M rate */
- /* mcs_rate = 3->CCK 11M rate */
- /* In the P2P mode, the driver should not support the CCK rate */
- /* Commented by Kurt 2012/10/16 */
- /* IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
- if (padapter->registrypriv.wifi_spec == 1) {
- if (pattrib->data_rate <= DESC_RATE11M)
- wifi_test_chk_rate = 0;
- }
- if (wifi_test_chk_rate == 1) {
- is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);
- if (is_valid_p2p_probereq == _TRUE) {
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
- /* FIXME */
- if (padapter->wdinfo.driver_interface == DRIVER_WEXT)
- report_survey_event(padapter, precv_frame);
- p2p_listen_state_process(padapter, get_sa(pframe));
- return _SUCCESS;
- }
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
- goto _continue;
- }
- }
- }
- _continue:
- #endif /* CONFIG_P2P */
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- return _SUCCESS;
- if (check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE &&
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE | WIFI_MESH_STATE) == _FALSE)
- return _SUCCESS;
- /* RTW_INFO("+OnProbeReq\n"); */
- #ifdef CONFIG_ATMEL_RC_PATCH
- wps_ie = rtw_get_wps_ie(
- pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_,
- len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_,
- NULL, &wps_ielen);
- if (wps_ie)
- target_ie = rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_MANUFACTURER, NULL, &target_ielen);
- if ((target_ie && (target_ielen == 4)) && (_TRUE == _rtw_memcmp((void *)target_ie, "Ozmo", 4))) {
- /* psta->flag_atmel_rc = 1; */
- unsigned char *sa_addr = get_sa(pframe);
- printk("%s: Find Ozmo RC -- %02x:%02x:%02x:%02x:%02x:%02x \n\n",
- __func__, *sa_addr, *(sa_addr + 1), *(sa_addr + 2), *(sa_addr + 3), *(sa_addr + 4), *(sa_addr + 5));
- _rtw_memcpy(pstapriv->atmel_rc_pattern, get_sa(pframe), ETH_ALEN);
- }
- #endif
- #ifdef CONFIG_AUTO_AP_MODE
- if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
- pmlmepriv->cur_network.join_res == _TRUE) {
- _irqL irqL;
- struct sta_info *psta;
- u8 *mac_addr, *peer_addr;
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
- /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen,
- len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
- if (!p || ielen != 14)
- goto _non_rc_device;
- if (!_rtw_memcmp(p + 2, RC_OUI, sizeof(RC_OUI)))
- goto _non_rc_device;
- if (!_rtw_memcmp(p + 6, get_sa(pframe), ETH_ALEN)) {
- RTW_INFO("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __FUNCTION__,
- MAC_ARG(get_sa(pframe)), MAC_ARG(p + 6));
- goto _non_rc_device;
- }
- RTW_INFO("%s, got the pairing device("MAC_FMT")\n", __FUNCTION__, MAC_ARG(get_sa(pframe)));
- /* new a station */
- psta = rtw_get_stainfo(pstapriv, get_sa(pframe));
- if (psta == NULL) {
- /* allocate a new one */
- RTW_INFO("going to alloc stainfo for rc="MAC_FMT"\n", MAC_ARG(get_sa(pframe)));
- psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));
- if (psta == NULL) {
- /* TODO: */
- RTW_INFO(" Exceed the upper limit of supported clients...\n");
- return _SUCCESS;
- }
- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- if (rtw_is_list_empty(&psta->asoc_list)) {
- psta->expire_to = pstapriv->expire_to;
- rtw_list_insert_tail(&psta->asoc_list, &pstapriv->asoc_list);
- pstapriv->asoc_list_cnt++;
- }
- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- /* generate pairing ID */
- mac_addr = adapter_mac_addr(padapter);
- peer_addr = psta->cmn.mac_addr;
- psta->pid = (u16)(((mac_addr[4] << 8) + mac_addr[5]) + ((peer_addr[4] << 8) + peer_addr[5]));
- /* update peer stainfo */
- psta->isrc = _TRUE;
- /* AID assignment */
- if (psta->cmn.aid > 0)
- RTW_INFO(FUNC_ADPT_FMT" old AID=%d\n", FUNC_ADPT_ARG(padapter), psta->cmn.aid);
- else {
- if (!rtw_aid_alloc(padapter, psta)) {
- RTW_INFO(FUNC_ADPT_FMT" no room for more AIDs\n", FUNC_ADPT_ARG(padapter));
- return _SUCCESS;
- }
- RTW_INFO(FUNC_ADPT_FMT" allocate new AID=%d\n", FUNC_ADPT_ARG(padapter), psta->cmn.aid);
- }
- psta->qos_option = 1;
- psta->cmn.bw_mode = CHANNEL_WIDTH_20;
- psta->ieee8021x_blocked = _FALSE;
- #ifdef CONFIG_80211N_HT
- if(padapter->registrypriv.ht_enable &&
- is_supported_ht(padapter->registrypriv.wireless_mode)) {
- psta->htpriv.ht_option = _TRUE;
- psta->htpriv.ampdu_enable = _FALSE;
- psta->htpriv.sgi_20m = _FALSE;
- psta->htpriv.sgi_40m = _FALSE;
- psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
- psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
- }
- #endif
- rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
- _rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
- _enter_critical_bh(&psta->lock, &irqL);
- psta->state |= _FW_LINKED;
- _exit_critical_bh(&psta->lock, &irqL);
- report_add_sta_event(padapter, psta->cmn.mac_addr);
- }
- issue_probersp(padapter, get_sa(pframe), _FALSE);
- return _SUCCESS;
- }
- _non_rc_device:
- return _SUCCESS;
- #endif /* CONFIG_AUTO_AP_MODE */
- #ifdef CONFIG_CONCURRENT_MODE
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) &&
- rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) {
- /* don't process probe req */
- return _SUCCESS;
- }
- #endif
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
- len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
- /* check (wildcard) SSID */
- if (p != NULL) {
- if (is_valid_p2p_probereq == _TRUE)
- goto _issue_probersp;
- if ((ielen != 0 && _FALSE == _rtw_memcmp((void *)(p + 2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
- || (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
- goto exit;
- #ifdef CONFIG_RTW_MESH
- if (MLME_IS_MESH(padapter)) {
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_MESH_ID, (int *)&ielen,
- len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
- if (!p)
- goto exit;
- if (ielen != 0 && _rtw_memcmp((void *)(p + 2), (void *)cur->mesh_id.Ssid, cur->mesh_id.SsidLength) == _FALSE)
- goto exit;
- }
- #endif
- _issue_probersp:
- if (((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
- pmlmepriv->cur_network.join_res == _TRUE)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- /* RTW_INFO("+issue_probersp during ap mode\n"); */
- issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
- }
- }
- exit:
- return _SUCCESS;
- }
- unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &padapter->wdinfo;
- #endif
- #ifdef CONFIG_P2P
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
- if (_TRUE == pwdinfo->tx_prov_disc_info.benable) {
- if (_rtw_memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, get_addr2_ptr(pframe), ETH_ALEN)) {
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
- pwdinfo->tx_prov_disc_info.benable = _FALSE;
- issue_p2p_provision_request(padapter,
- pwdinfo->tx_prov_disc_info.ssid.Ssid,
- pwdinfo->tx_prov_disc_info.ssid.SsidLength,
- pwdinfo->tx_prov_disc_info.peerDevAddr);
- } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- pwdinfo->tx_prov_disc_info.benable = _FALSE;
- issue_p2p_provision_request(padapter,
- NULL,
- 0,
- pwdinfo->tx_prov_disc_info.peerDevAddr);
- }
- }
- }
- return _SUCCESS;
- } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
- if (_TRUE == pwdinfo->nego_req_info.benable) {
- RTW_INFO("[%s] P2P State is GONEGO ING!\n", __FUNCTION__);
- if (_rtw_memcmp(pwdinfo->nego_req_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN)) {
- pwdinfo->nego_req_info.benable = _FALSE;
- issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
- }
- }
- } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
- if (_TRUE == pwdinfo->invitereq_info.benable) {
- RTW_INFO("[%s] P2P_STATE_TX_INVITE_REQ!\n", __FUNCTION__);
- if (_rtw_memcmp(pwdinfo->invitereq_info.peer_macaddr, get_addr2_ptr(pframe), ETH_ALEN)) {
- pwdinfo->invitereq_info.benable = _FALSE;
- issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
- }
- }
- }
- #endif
- if ((mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS))
- || (MLME_IS_MESH(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))
- #ifdef CONFIG_RTW_REPEATER_SON
- || (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS)
- #endif
- ) {
- rtw_mi_report_survey_event(padapter, precv_frame);
- return _SUCCESS;
- }
- #if 0 /* move to validate_recv_mgnt_frame */
- if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
- psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (psta != NULL)
- psta->sta_stats.rx_mgnt_pkts++;
- }
- }
- #endif
- return _SUCCESS;
- }
- /* for 11n Logo 4.2.31/4.2.32 */
- static void rtw_check_legacy_ap(_adapter *padapter, u8 *pframe, u32 len)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- if (!padapter->registrypriv.wifi_spec)
- return;
-
- if(!MLME_IS_AP(padapter))
- return;
-
- if (pmlmeext->bstart_bss == _TRUE) {
- int left;
- unsigned char *pos;
- struct rtw_ieee802_11_elems elems;
- #ifdef CONFIG_80211N_HT
- u16 cur_op_mode;
- #endif
- /* checking IEs */
- left = len - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_;
- pos = pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_;
- if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {
- RTW_INFO("%s: parse fail for "MAC_FMT"\n", __func__, MAC_ARG(GetAddr3Ptr(pframe)));
- return;
- }
- #ifdef CONFIG_80211N_HT
- cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
- #endif
- /* for legacy ap */
- if (elems.ht_capabilities == NULL && elems.ht_capabilities_len == 0) {
- if (0)
- RTW_INFO("%s: "MAC_FMT" is legacy ap\n", __func__, MAC_ARG(GetAddr3Ptr(pframe)));
- ATOMIC_SET(&pmlmepriv->olbc, _TRUE);
- ATOMIC_SET(&pmlmepriv->olbc_ht, _TRUE);
- }
-
- }
- }
- unsigned int OnBeacon(_adapter *padapter, union recv_frame *precv_frame)
- {
- struct sta_info *psta;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint len = precv_frame->u.hdr.len;
- WLAN_BSSID_EX *pbss;
- int ret = _SUCCESS;
- #ifdef CONFIG_TDLS
- struct sta_info *ptdls_sta;
- struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
- #ifdef CONFIG_TDLS_CH_SW
- struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
- #endif
- #endif /* CONFIG_TDLS */
- if (validate_beacon_len(pframe, len) == _FALSE)
- return _SUCCESS;
- if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS)
- || (MLME_IS_MESH(padapter) && check_fwstate(pmlmepriv, WIFI_ASOC_STATE))
- ) {
- rtw_mi_report_survey_event(padapter, precv_frame);
- return _SUCCESS;
- }
- #ifdef CONFIG_RTW_REPEATER_SON
- if (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS)
- rtw_mi_report_survey_event(padapter, precv_frame);
- #endif
- rtw_check_legacy_ap(padapter, pframe, len);
- if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
- if ((pmlmeinfo->state & WIFI_FW_AUTH_NULL)
- && (rtw_sta_linking_test_wait_done() || pmlmeext->join_abort)
- ) {
- if (rtw_sta_linking_test_force_fail() || pmlmeext->join_abort) {
- set_link_timer(pmlmeext, 1);
- return _SUCCESS;
- }
- /* we should update current network before auth, or some IE is wrong */
- pbss = (WLAN_BSSID_EX *)rtw_malloc(sizeof(WLAN_BSSID_EX));
- if (pbss) {
- if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
- struct beacon_keys recv_beacon;
- update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);
- rtw_get_bcn_info(&(pmlmepriv->cur_network));
- /* update bcn keys */
- if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) {
- RTW_INFO("%s: beacon keys ready\n", __func__);
- _rtw_memcpy(&pmlmepriv->cur_beacon_keys,
- &recv_beacon, sizeof(recv_beacon));
- } else {
- RTW_ERR("%s: get beacon keys failed\n", __func__);
- _rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon));
- }
- #ifdef CONFIG_BCN_CNT_CONFIRM_HDL
- pmlmepriv->new_beacon_cnts = 0;
- #endif
- }
- rtw_mfree((u8 *)pbss, sizeof(WLAN_BSSID_EX));
- }
- /* check the vendor of the assoc AP */
- pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct rtw_ieee80211_hdr_3addr), len - sizeof(struct rtw_ieee80211_hdr_3addr));
- /* update TSF Value */
- update_TSF(pmlmeext, pframe, len);
- pmlmeext->bcn_cnt = 0;
- pmlmeext->last_bcn_cnt = 0;
- #ifdef CONFIG_P2P_PS
- /* Comment by YiWei , in wifi p2p spec the "3.3 P2P Power Management" , "These mechanisms are available in a P2P Group in which only P2P Devices are associated." */
- /* process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)); */
- #endif /* CONFIG_P2P_PS */
- #if defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)
- if (padapter->registrypriv.wifi_spec) {
- if (process_p2p_cross_connect_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)) == _FALSE) {
- if (rtw_mi_buddy_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {
- RTW_PRINT("no issue auth, P2P cross-connect does not permit\n ");
- return _SUCCESS;
- }
- }
- }
- #endif /* CONFIG_P2P CONFIG_P2P and CONFIG_CONCURRENT_MODE */
- /* start auth */
- start_clnt_auth(padapter);
- return _SUCCESS;
- }
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
- psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (psta != NULL) {
- #ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL
- /* Merge from 8712 FW code */
- if (cmp_pkt_chnl_diff(padapter, pframe, len) != 0) {
- /* join wrong channel, deauth and reconnect */
- issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
- report_del_sta_event(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_JOIN_WRONG_CHANNEL, _TRUE, _FALSE);
- pmlmeinfo->state &= (~WIFI_FW_ASSOC_SUCCESS);
- return _SUCCESS;
- }
- #endif /* CONFIG_PATCH_JOIN_WRONG_CHANNEL */
- #ifdef CONFIG_RTW_80211R
- rtw_ft_update_bcn(padapter, precv_frame);
- #endif
- ret = rtw_check_bcn_info(padapter, pframe, len);
- if (!ret) {
- RTW_PRINT("ap has changed, disconnect now\n ");
- receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 0, _FALSE);
- return _SUCCESS;
- }
- /* update WMM, ERP in the beacon */
- /* todo: the timer is used instead of the number of the beacon received */
- if ((sta_rx_pkts(psta) & 0xf) == 0) {
- /* RTW_INFO("update_bcn_info\n"); */
- update_beacon_info(padapter, pframe, len, psta);
- }
- pmlmepriv->cur_network_scanned->network.Rssi = precv_frame->u.hdr.attrib.phy_info.recv_signal_power;
- pmlmeext->bcn_cnt++;
- #ifdef CONFIG_BCN_RECV_TIME
- rtw_rx_bcn_time_update(padapter, len, precv_frame->u.hdr.attrib.data_rate);
- #endif
- #ifdef CONFIG_TDLS
- #ifdef CONFIG_TDLS_CH_SW
- if (rtw_tdls_is_chsw_allowed(padapter) == _TRUE) {
- /* Send TDLS Channel Switch Request when receiving Beacon */
- if ((padapter->tdlsinfo.chsw_info.ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) && (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE)
- && (pmlmeext->cur_channel == rtw_get_oper_ch(padapter))) {
- ptdls_sta = rtw_get_stainfo(&padapter->stapriv, padapter->tdlsinfo.chsw_info.addr);
- if (ptdls_sta != NULL) {
- if (ptdls_sta->tdls_sta_state | TDLS_LINKED_STATE)
- _set_timer(&ptdls_sta->stay_on_base_chnl_timer, TDLS_CH_SW_STAY_ON_BASE_CHNL_TIMEOUT);
- }
- }
- }
- #endif
- #endif /* CONFIG_TDLS */
- #ifdef CONFIG_DFS
- process_csa_ie(padapter
- , pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_
- , len - (WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_));
- #endif
- #ifdef CONFIG_P2P_PS
- process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
- #endif /* CONFIG_P2P_PS */
- if (pmlmeext->tsf_update_required && pmlmeext->en_hw_update_tsf)
- rtw_enable_hw_update_tsf_cmd(padapter);
- #if 0 /* move to validate_recv_mgnt_frame */
- psta->sta_stats.rx_mgnt_pkts++;
- #endif
- }
- } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- u8 rate_set[16];
- u8 rate_num = 0;
- psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (psta != NULL) {
- /*
- * update WMM, ERP in the beacon
- * todo: the timer is used instead of the number of the beacon received
- */
- if ((sta_rx_pkts(psta) & 0xf) == 0)
- update_beacon_info(padapter, pframe, len, psta);
- if (pmlmeext->tsf_update_required && pmlmeext->en_hw_update_tsf)
- rtw_enable_hw_update_tsf_cmd(padapter);
- } else {
- rtw_ies_get_supported_rate(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_, rate_set, &rate_num);
- if (rate_num == 0) {
- RTW_INFO(FUNC_ADPT_FMT" RX beacon with no supported rate\n", FUNC_ADPT_ARG(padapter));
- goto _END_ONBEACON_;
- }
- psta = rtw_alloc_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (psta == NULL) {
- RTW_INFO(FUNC_ADPT_FMT" Exceed the upper limit of supported clients\n", FUNC_ADPT_ARG(padapter));
- goto _END_ONBEACON_;
- }
- psta->expire_to = pstapriv->adhoc_expire_to;
- _rtw_memcpy(psta->bssrateset, rate_set, rate_num);
- psta->bssratelen = rate_num;
- /* update TSF Value */
- update_TSF(pmlmeext, pframe, len);
- /* report sta add event */
- report_add_sta_event(padapter, get_addr2_ptr(pframe));
- }
- }
- }
- _END_ONBEACON_:
- return _SUCCESS;
- }
- unsigned int OnAuth(_adapter *padapter, union recv_frame *precv_frame)
- {
- #ifdef CONFIG_AP_MODE
- _irqL irqL;
- unsigned int auth_mode, seq, ie_len;
- unsigned char *sa, *p;
- u16 algorithm;
- int status;
- static struct sta_info stat;
- struct sta_info *pstat = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint len = precv_frame->u.hdr.len;
- u8 offset = 0;
- #ifdef CONFIG_CONCURRENT_MODE
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) &&
- rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) {
- /* don't process auth request; */
- return _SUCCESS;
- }
- #endif /* CONFIG_CONCURRENT_MODE */
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- return _FAIL;
- if (!MLME_IS_ASOC(padapter))
- return _SUCCESS;
- #if defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_RTW_MESH)
- if (MLME_IS_MESH(padapter))
- return rtw_mesh_on_auth(padapter, precv_frame);
- #endif
- RTW_INFO("+OnAuth\n");
- sa = get_addr2_ptr(pframe);
- auth_mode = psecuritypriv->dot11AuthAlgrthm;
- if (GetPrivacy(pframe)) {
- u8 *iv;
- struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib);
- prxattrib->hdrlen = WLAN_HDR_A3_LEN;
- prxattrib->encrypt = _WEP40_;
- iv = pframe + prxattrib->hdrlen;
- prxattrib->key_index = ((iv[3] >> 6) & 0x3);
- prxattrib->iv_len = 4;
- prxattrib->icv_len = 4;
- rtw_wep_decrypt(padapter, (u8 *)precv_frame);
- offset = 4;
- }
- algorithm = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
- seq = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
- RTW_INFO("auth alg=%x, seq=%X\n", algorithm, seq);
- if (rtw_ap_linking_test_force_auth_fail()) {
- status = rtw_ap_linking_test_force_auth_fail();
- RTW_INFO(FUNC_ADPT_FMT" force auth fail with status:%u\n"
- , FUNC_ADPT_ARG(padapter), status);
- goto auth_fail;
- }
- if (auth_mode == 2 &&
- psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
- psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
- auth_mode = 0;
- if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */
- (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */
- RTW_INFO("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
- algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
- status = _STATS_NO_SUPP_ALG_;
- goto auth_fail;
- }
- #if CONFIG_RTW_MACADDR_ACL
- if (rtw_access_ctrl(padapter, sa) == _FALSE) {
- status = _STATS_UNABLE_HANDLE_STA_;
- goto auth_fail;
- }
- #endif
- pstat = rtw_get_stainfo(pstapriv, sa);
- if (pstat == NULL) {
- /* allocate a new one */
- RTW_INFO("going to alloc stainfo for sa="MAC_FMT"\n", MAC_ARG(sa));
- pstat = rtw_alloc_stainfo(pstapriv, sa);
- if (pstat == NULL) {
- RTW_INFO(" Exceed the upper limit of supported clients...\n");
- status = _STATS_UNABLE_HANDLE_STA_;
- goto auth_fail;
- }
- pstat->state = WIFI_FW_AUTH_NULL;
- pstat->auth_seq = 0;
- /* pstat->flags = 0; */
- /* pstat->capability = 0; */
- } else {
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS))
- #endif /* CONFIG_IEEE80211W */
- {
- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- if (rtw_is_list_empty(&pstat->asoc_list) == _FALSE) {
- rtw_list_delete(&pstat->asoc_list);
- pstapriv->asoc_list_cnt--;
- if (pstat->expire_to > 0)
- ;/* TODO: STA re_auth within expire_to */
- }
- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- if (seq == 1)
- ; /* TODO: STA re_auth and auth timeout */
- }
- }
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS))
- #endif /* CONFIG_IEEE80211W */
- {
- _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
- if (rtw_is_list_empty(&pstat->auth_list)) {
- rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
- pstapriv->auth_list_cnt++;
- }
- _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
- }
- if (pstat->auth_seq == 0)
- pstat->expire_to = pstapriv->auth_to;
- if ((pstat->auth_seq + 1) != seq) {
- RTW_INFO("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
- seq, pstat->auth_seq + 1);
- status = _STATS_OUT_OF_AUTH_SEQ_;
- goto auth_fail;
- }
- if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {
- if (seq == 1) {
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS))
- #endif /* CONFIG_IEEE80211W */
- {
- pstat->state &= ~WIFI_FW_AUTH_NULL;
- pstat->state |= WIFI_FW_AUTH_SUCCESS;
- pstat->expire_to = pstapriv->assoc_to;
- }
- pstat->authalg = algorithm;
- } else {
- RTW_INFO("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
- seq, pstat->auth_seq + 1);
- status = _STATS_OUT_OF_AUTH_SEQ_;
- goto auth_fail;
- }
- } else { /* shared system or auto authentication */
- if (seq == 1) {
- /* prepare for the challenging txt... */
- /* get_random_bytes((void *)pstat->chg_txt, 128); */ /* TODO: */
- _rtw_memset((void *)pstat->chg_txt, 78, 128);
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS))
- #endif /* CONFIG_IEEE80211W */
- {
- pstat->state &= ~WIFI_FW_AUTH_NULL;
- pstat->state |= WIFI_FW_AUTH_STATE;
- }
- pstat->authalg = algorithm;
- pstat->auth_seq = 2;
- } else if (seq == 3) {
- /* checking for challenging txt... */
- RTW_INFO("checking for challenging txt...\n");
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,
- len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
- if ((p == NULL) || (ie_len <= 0)) {
- RTW_INFO("auth rejected because challenge failure!(1)\n");
- status = _STATS_CHALLENGE_FAIL_;
- goto auth_fail;
- }
- if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS))
- #endif /* CONFIG_IEEE80211W */
- {
- pstat->state &= (~WIFI_FW_AUTH_STATE);
- pstat->state |= WIFI_FW_AUTH_SUCCESS;
- /* challenging txt is correct... */
- pstat->expire_to = pstapriv->assoc_to;
- }
- } else {
- RTW_INFO("auth rejected because challenge failure!\n");
- status = _STATS_CHALLENGE_FAIL_;
- goto auth_fail;
- }
- } else {
- RTW_INFO("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
- seq, pstat->auth_seq + 1);
- status = _STATS_OUT_OF_AUTH_SEQ_;
- goto auth_fail;
- }
- }
- /* Now, we are going to issue_auth... */
- pstat->auth_seq = seq + 1;
- #ifdef CONFIG_NATIVEAP_MLME
- issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
- #endif
- if ((pstat->state & WIFI_FW_AUTH_SUCCESS) || (pstat->state & WIFI_FW_ASSOC_SUCCESS))
- pstat->auth_seq = 0;
- return _SUCCESS;
- auth_fail:
- if (pstat)
- rtw_free_stainfo(padapter , pstat);
- pstat = &stat;
- _rtw_memset((char *)pstat, '\0', sizeof(stat));
- pstat->auth_seq = 2;
- _rtw_memcpy(pstat->cmn.mac_addr, sa, ETH_ALEN);
- #ifdef CONFIG_NATIVEAP_MLME
- issue_auth(padapter, pstat, (unsigned short)status);
- #endif
- #endif
- return _FAIL;
- }
- unsigned int OnAuthClient(_adapter *padapter, union recv_frame *precv_frame)
- {
- unsigned int seq, len, status, algthm, offset;
- unsigned char *p;
- unsigned int go2asoc = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint pkt_len = precv_frame->u.hdr.len;
- RTW_INFO("%s\n", __FUNCTION__);
- /* check A1 matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))
- return _SUCCESS;
- if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE) || pmlmeext->join_abort)
- return _SUCCESS;
- offset = (GetPrivacy(pframe)) ? 4 : 0;
- algthm = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
- seq = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
- status = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
- if (status != 0) {
- RTW_INFO("clnt auth fail, status: %d\n", status);
- if (status == 13) { /* && pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
- if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
- pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
- else
- pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
- /* pmlmeinfo->reauth_count = 0; */
- }
- pmlmeinfo->auth_status = status;
- set_link_timer(pmlmeext, 1);
- goto authclnt_fail;
- }
- if (seq == 2) {
- if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
- /* legendary shared system */
- p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
- pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
- if (p == NULL) {
- /* RTW_INFO("marc: no challenge text?\n"); */
- goto authclnt_fail;
- }
- _rtw_memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
- pmlmeinfo->auth_seq = 3;
- issue_auth(padapter, NULL, 0);
- set_link_timer(pmlmeext, REAUTH_TO);
- return _SUCCESS;
- } else {
- /* open, or 802.11r FTAA system */
- go2asoc = 1;
- }
- } else if (seq == 4) {
- if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
- go2asoc = 1;
- else
- goto authclnt_fail;
- } else {
- /* this is also illegal */
- /* RTW_INFO("marc: clnt auth failed due to illegal seq=%x\n", seq); */
- goto authclnt_fail;
- }
- if (go2asoc) {
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_update_auth_rsp_ies(padapter, pframe, pkt_len))
- return _SUCCESS;
- #endif
- RTW_PRINT("auth success, start assoc\n");
- start_clnt_assoc(padapter);
- return _SUCCESS;
- }
- authclnt_fail:
- /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
- return _FAIL;
- }
- unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame)
- {
- #ifdef CONFIG_AP_MODE
- _irqL irqL;
- u16 listen_interval;
- struct rtw_ieee802_11_elems elems;
- struct sta_info *pstat;
- unsigned char reassoc, *pos;
- int left;
- unsigned short status = _STATS_SUCCESSFUL_;
- unsigned short frame_type, ie_offset = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *cur = &(pmlmeinfo->network);
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint pkt_len = precv_frame->u.hdr.len;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- u8 p2p_status_code = P2P_STATUS_SUCCESS;
- u8 *p2pie;
- u32 p2pielen = 0;
- #endif /* CONFIG_P2P */
- #ifdef CONFIG_CONCURRENT_MODE
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) &&
- rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) {
- /* don't process assoc request; */
- return _SUCCESS;
- }
- #endif /* CONFIG_CONCURRENT_MODE */
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- return _FAIL;
- frame_type = get_frame_sub_type(pframe);
- if (frame_type == WIFI_ASSOCREQ) {
- reassoc = 0;
- ie_offset = _ASOCREQ_IE_OFFSET_;
- } else { /* WIFI_REASSOCREQ */
- reassoc = 1;
- ie_offset = _REASOCREQ_IE_OFFSET_;
- }
- if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
- RTW_INFO("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
- "\n", reassoc, (unsigned long)pkt_len);
- return _FAIL;
- }
- pstat = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (pstat == (struct sta_info *)NULL) {
- status = _RSON_CLS2_;
- goto asoc_class2_error;
- }
- RTW_INFO("%s\n", __FUNCTION__);
- /* check if this stat has been successfully authenticated/assocated */
- if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
- if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
- status = _RSON_CLS2_;
- goto asoc_class2_error;
- } else {
- pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
- pstat->state |= WIFI_FW_ASSOC_STATE;
- }
- } else {
- pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
- pstat->state |= WIFI_FW_ASSOC_STATE;
- }
- #if 0/* todo:tkip_countermeasures */
- if (hapd->tkip_countermeasures) {
- resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
- goto fail;
- }
- #endif
- if (rtw_ap_linking_test_force_asoc_fail()) {
- status = rtw_ap_linking_test_force_asoc_fail();
- RTW_INFO(FUNC_ADPT_FMT" force asoc fail with status:%u\n"
- , FUNC_ADPT_ARG(padapter), status);
- goto OnAssocReqFail;
- }
- /* now parse all ieee802_11 ie to point to elems */
- left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
- pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
- if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {
- RTW_INFO("STA " MAC_FMT " sent invalid association request\n",
- MAC_ARG(pstat->cmn.mac_addr));
- status = _STATS_FAILURE_;
- goto OnAssocReqFail;
- }
- rtw_ap_parse_sta_capability(padapter, pstat, pframe + WLAN_HDR_A3_LEN);
- listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN + 2);
- #if 0/* todo: */
- /* check listen_interval */
- if (listen_interval > hapd->conf->max_listen_interval) {
- hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG,
- "Too large Listen Interval (%d)",
- listen_interval);
- resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
- goto fail;
- }
- pstat->listen_interval = listen_interval;
- #endif
- /* now we should check all the fields... */
- /* checking SSID */
- if (elems.ssid == NULL
- || elems.ssid_len == 0
- || elems.ssid_len != cur->Ssid.SsidLength
- || _rtw_memcmp(elems.ssid, cur->Ssid.Ssid, cur->Ssid.SsidLength) == _FALSE
- ) {
- status = _STATS_FAILURE_;
- goto OnAssocReqFail;
- }
- /* (Extended) Supported rates */
- status = rtw_ap_parse_sta_supported_rates(padapter, pstat
- , pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
- if (status != _STATS_SUCCESSFUL_)
- goto OnAssocReqFail;
- /* check RSN/WPA/WPS */
- status = rtw_ap_parse_sta_security_ie(padapter, pstat, &elems);
- if (status != _STATS_SUCCESSFUL_)
- goto OnAssocReqFail;
- /* check if there is WMM IE & support WWM-PS */
- rtw_ap_parse_sta_wmm_ie(padapter, pstat
- , pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
- rtw_ap_parse_sta_ht_ie(padapter, pstat, &elems);
- rtw_ap_parse_sta_vht_ie(padapter, pstat, &elems);
- if (((pstat->flags & WLAN_STA_HT) || (pstat->flags & WLAN_STA_VHT)) &&
- ((pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
- (pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP))) {
- RTW_INFO("(V)HT: " MAC_FMT " tried to use TKIP with (V)HT association\n", MAC_ARG(pstat->cmn.mac_addr));
- pstat->flags &= ~WLAN_STA_HT;
- pstat->flags &= ~WLAN_STA_VHT;
- /*status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
- * goto OnAssocReqFail;
- */
- }
- if (status != _STATS_SUCCESSFUL_)
- goto OnAssocReqFail;
- #ifdef CONFIG_P2P
- pstat->is_p2p_device = _FALSE;
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen);
- if (p2pie) {
- pstat->is_p2p_device = _TRUE;
- p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);
- if (p2p_status_code > 0) {
- pstat->p2p_status_code = p2p_status_code;
- status = _STATS_CAP_FAIL_;
- goto OnAssocReqFail;
- }
- }
- #ifdef CONFIG_WFD
- rtw_process_wfd_ies(padapter, pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, __func__);
- #endif
- }
- pstat->p2p_status_code = p2p_status_code;
- #endif /* CONFIG_P2P */
- #ifdef CONFIG_RTW_REPEATER_SON
- if (rtw_rson_ap_check_sta(padapter, pframe, pkt_len, ie_offset))
- goto OnAssocReqFail;
- #endif
- /* TODO: identify_proprietary_vendor_ie(); */
- /* Realtek proprietary IE */
- /* identify if this is Broadcom sta */
- /* identify if this is ralink sta */
- /* Customer proprietary IE */
- #ifdef CONFIG_RTW_80211K
- rtw_ap_parse_sta_rm_en_cap(padapter, pstat, &elems);
- #endif
- /* AID assignment */
- if (pstat->cmn.aid > 0)
- RTW_INFO(FUNC_ADPT_FMT" old AID=%d\n", FUNC_ADPT_ARG(padapter), pstat->cmn.aid);
- else {
- if (!rtw_aid_alloc(padapter, pstat)) {
- RTW_INFO(FUNC_ADPT_FMT" no room for more AIDs\n", FUNC_ADPT_ARG(padapter));
- status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
- goto OnAssocReqFail;
- }
- RTW_INFO(FUNC_ADPT_FMT" allocate new AID=%d\n", FUNC_ADPT_ARG(padapter), pstat->cmn.aid);
- }
- pstat->state &= (~WIFI_FW_ASSOC_STATE);
- pstat->state |= WIFI_FW_ASSOC_SUCCESS;
- /* RTW_INFO("==================%s, %d, (%x), bpairwise_key_installed=%d, MAC:"MAC_FMT"\n"
- , __func__, __LINE__, pstat->state, pstat->bpairwise_key_installed, MAC_ARG(pstat->cmn.mac_addr)); */
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE)
- #endif /* CONFIG_IEEE80211W */
- {
- _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
- if (!rtw_is_list_empty(&pstat->auth_list)) {
- rtw_list_delete(&pstat->auth_list);
- pstapriv->auth_list_cnt--;
- }
- _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- if (rtw_is_list_empty(&pstat->asoc_list)) {
- pstat->expire_to = pstapriv->expire_to;
- rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
- pstapriv->asoc_list_cnt++;
- }
- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- }
- /* now the station is qualified to join our BSS... */
- if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
- #ifdef CONFIG_NATIVEAP_MLME
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE)
- #endif /* CONFIG_IEEE80211W */
- {
- /* .1 bss_cap_update & sta_info_update */
- bss_cap_update_on_sta_join(padapter, pstat);
- sta_info_update(padapter, pstat);
- }
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed == _TRUE)
- status = _STATS_REFUSED_TEMPORARILY_;
- #endif /* CONFIG_IEEE80211W */
- /* .2 issue assoc rsp before notify station join event. */
- if (frame_type == WIFI_ASSOCREQ)
- issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
- else
- issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
- #ifdef CONFIG_IOCTL_CFG80211
- _enter_critical_bh(&pstat->lock, &irqL);
- if (pstat->passoc_req) {
- rtw_mfree(pstat->passoc_req, pstat->assoc_req_len);
- pstat->passoc_req = NULL;
- pstat->assoc_req_len = 0;
- }
- pstat->passoc_req = rtw_zmalloc(pkt_len);
- if (pstat->passoc_req) {
- _rtw_memcpy(pstat->passoc_req, pframe, pkt_len);
- pstat->assoc_req_len = pkt_len;
- }
- _exit_critical_bh(&pstat->lock, &irqL);
- #endif /* CONFIG_IOCTL_CFG80211 */
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed != _TRUE)
- #endif /* CONFIG_IEEE80211W */
- {
- /* .3-(1) report sta add event */
- report_add_sta_event(padapter, pstat->cmn.mac_addr);
- }
- #ifdef CONFIG_IEEE80211W
- if (pstat->bpairwise_key_installed == _TRUE && SEC_IS_BIP_KEY_INSTALLED(&padapter->securitypriv) == _TRUE) {
- RTW_INFO(MAC_FMT"\n", MAC_ARG(pstat->cmn.mac_addr));
- issue_action_SA_Query(padapter, pstat->cmn.mac_addr, 0, 0, IEEE80211W_RIGHT_KEY);
- }
- #endif /* CONFIG_IEEE80211W */
- #endif /* CONFIG_NATIVEAP_MLME */
- }
- return _SUCCESS;
- asoc_class2_error:
- #ifdef CONFIG_NATIVEAP_MLME
- issue_deauth(padapter, (void *)get_addr2_ptr(pframe), status);
- #endif
- return _FAIL;
- OnAssocReqFail:
- #ifdef CONFIG_NATIVEAP_MLME
- pstat->cmn.aid = 0;
- if (frame_type == WIFI_ASSOCREQ)
- issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
- else
- issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
- #endif
- #endif /* CONFIG_AP_MODE */
- return _FAIL;
- }
- #if defined(CONFIG_LAYER2_ROAMING) && defined(CONFIG_RTW_80211K)
- void rtw_roam_nb_discover(_adapter *padapter, u8 bfroce)
- {
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *psta;
- u8 nb_req_issue = _FALSE;
- if (!check_fwstate(pmlmepriv, _FW_LINKED))
- return;
- if (!rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE))
- return;
- psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
- if (!psta)
- return;
-
- if (bfroce || (!pmlmepriv->nb_info.nb_rpt_is_same))
- nb_req_issue = _TRUE;
-
- if (nb_req_issue && (psta->rm_en_cap[0] & RTW_RRM_NB_RPT_EN))
- rm_add_nb_req(padapter, psta);
- }
- #endif
- unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame)
- {
- uint i;
- int res;
- unsigned short status;
- PNDIS_802_11_VARIABLE_IEs pIE;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- /* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint pkt_len = precv_frame->u.hdr.len;
- #ifdef CONFIG_WAPI_SUPPORT
- PNDIS_802_11_VARIABLE_IEs pWapiIE = NULL;
- #endif
- RTW_INFO("%s\n", __FUNCTION__);
- /* check A1 matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))
- return _SUCCESS;
- if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)) || pmlmeext->join_abort)
- return _SUCCESS;
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
- return _SUCCESS;
- _cancel_timer_ex(&pmlmeext->link_timer);
- /* status */
- status = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 2));
- if (status > 0) {
- RTW_INFO("assoc reject, status code: %d\n", status);
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- res = -4;
- goto report_assoc_result;
- }
- /* get capabilities */
- pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
- /* set slot time */
- pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
- /* AID */
- res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 4)) & 0x3fff);
- /* following are moved to join event callback function */
- /* to handle HT, WMM, rate adaptive, update MAC reg */
- /* for not to handle the synchronous IO in the tasklet */
- for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
- pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i);
- switch (pIE->ElementID) {
- case _VENDOR_SPECIFIC_IE_:
- if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
- WMM_param_handler(padapter, pIE);
- #if defined(CONFIG_P2P) && defined(CONFIG_WFD)
- else if (_rtw_memcmp(pIE->data, WFD_OUI, 4)) /* WFD */
- rtw_process_wfd_ie(padapter, (u8 *)pIE, pIE->Length, __func__);
- #endif
- break;
- #ifdef CONFIG_WAPI_SUPPORT
- case _WAPI_IE_:
- pWapiIE = pIE;
- break;
- #endif
- case _HT_CAPABILITY_IE_: /* HT caps */
- HT_caps_handler(padapter, pIE);
- #ifdef ROKU_PRIVATE
- HT_caps_handler_infra_ap(padapter, pIE);
- #endif /* ROKU_PRIVATE */
- break;
- case _HT_EXTRA_INFO_IE_: /* HT info */
- HT_info_handler(padapter, pIE);
- break;
- #ifdef CONFIG_80211AC_VHT
- case EID_VHTCapability:
- VHT_caps_handler(padapter, pIE);
- #ifdef ROKU_PRIVATE
- VHT_caps_handler_infra_ap(padapter, pIE);
- #endif /* ROKU_PRIVATE */
- break;
- case EID_VHTOperation:
- VHT_operation_handler(padapter, pIE);
- break;
- #endif
- case _ERPINFO_IE_:
- ERP_IE_handler(padapter, pIE);
- break;
- #ifdef CONFIG_TDLS
- case _EXT_CAP_IE_:
- if (check_ap_tdls_prohibited(pIE->data, pIE->Length) == _TRUE)
- padapter->tdlsinfo.ap_prohibited = _TRUE;
- if (check_ap_tdls_ch_switching_prohibited(pIE->data, pIE->Length) == _TRUE)
- padapter->tdlsinfo.ch_switch_prohibited = _TRUE;
- break;
- #endif /* CONFIG_TDLS */
- #ifdef CONFIG_RTW_80211K
- case _EID_RRM_EN_CAP_IE_:
- RM_IE_handler(padapter, pIE);
- break;
- #endif
- #ifdef ROKU_PRIVATE
- /* Infra mode, used to store AP's info , Parse the supported rates from AssocRsp */
- case _SUPPORTEDRATES_IE_:
- Supported_rate_infra_ap(padapter, pIE);
- break;
- case _EXT_SUPPORTEDRATES_IE_:
- Extended_Supported_rate_infra_ap(padapter, pIE);
- break;
- #endif /* ROKU_PRIVATE */
- default:
- break;
- }
- i += (pIE->Length + 2);
- }
- #ifdef CONFIG_WAPI_SUPPORT
- rtw_wapi_on_assoc_ok(padapter, pIE);
- #endif
- pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
- pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
- /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
- UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
- report_assoc_result:
- if (res > 0)
- rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
- else
- rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
- report_join_res(padapter, res, status);
- #if defined(CONFIG_LAYER2_ROAMING) && defined(CONFIG_RTW_80211K)
- rtw_roam_nb_discover(padapter, _TRUE);
- #endif
- return _SUCCESS;
- }
- unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame)
- {
- unsigned short reason;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 *pframe = precv_frame->u.hdr.rx_data;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #endif /* CONFIG_P2P */
- /* check A3 */
- if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
- return _SUCCESS;
- RTW_INFO(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter));
- #ifdef CONFIG_P2P
- if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
- _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
- _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
- }
- #endif /* CONFIG_P2P */
- reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
- #ifdef CONFIG_AP_MODE
- if (MLME_IS_AP(padapter)) {
- _irqL irqL;
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
- /* rtw_free_stainfo(padapter, psta); */
- /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
- RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
- , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe));
- psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (psta) {
- u8 updated = _FALSE;
- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {
- rtw_list_delete(&psta->asoc_list);
- pstapriv->asoc_list_cnt--;
- updated = ap_free_sta(padapter, psta, _FALSE, reason, _TRUE);
- }
- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
- }
- return _SUCCESS;
- } else
- #endif
- if (!MLME_IS_MESH(padapter)) {
- int ignore_received_deauth = 0;
- /* Commented by Albert 20130604 */
- /* Before sending the auth frame to start the STA/GC mode connection with AP/GO, */
- /* we will send the deauth first. */
- /* However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */
- /* Added the following code to avoid this case. */
- if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
- (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
- if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA)
- ignore_received_deauth = 1;
- else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
- /* TODO: 802.11r */
- ignore_received_deauth = 1;
- }
- }
- RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM, ignore=%d\n"
- , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe), ignore_received_deauth);
- if (0 == ignore_received_deauth)
- receive_disconnect(padapter, get_addr2_ptr(pframe), reason, _FALSE);
- }
- pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
- return _SUCCESS;
- }
- unsigned int OnDisassoc(_adapter *padapter, union recv_frame *precv_frame)
- {
- unsigned short reason;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 *pframe = precv_frame->u.hdr.rx_data;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #endif /* CONFIG_P2P */
- /* check A3 */
- if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
- return _SUCCESS;
- RTW_INFO(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter));
- #ifdef CONFIG_P2P
- if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
- _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
- _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
- }
- #endif /* CONFIG_P2P */
- reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
- #ifdef CONFIG_AP_MODE
- if (MLME_IS_AP(padapter)) {
- _irqL irqL;
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
- /* rtw_free_stainfo(padapter, psta); */
- /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
- RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
- , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe));
- psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (psta) {
- u8 updated = _FALSE;
- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {
- rtw_list_delete(&psta->asoc_list);
- pstapriv->asoc_list_cnt--;
- updated = ap_free_sta(padapter, psta, _FALSE, reason, _TRUE);
- }
- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
- }
- return _SUCCESS;
- } else
- #endif
- if (!MLME_IS_MESH(padapter)) {
- RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
- , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe));
- receive_disconnect(padapter, get_addr2_ptr(pframe), reason, _FALSE);
- }
- pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
- return _SUCCESS;
- }
- unsigned int OnAtim(_adapter *padapter, union recv_frame *precv_frame)
- {
- RTW_INFO("%s\n", __FUNCTION__);
- return _SUCCESS;
- }
- unsigned int on_action_spct_ch_switch(_adapter *padapter, struct sta_info *psta, u8 *ies, uint ies_len)
- {
- unsigned int ret = _FAIL;
- struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(mlmeext->mlmext_info);
- if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
- ret = _SUCCESS;
- goto exit;
- }
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
- int ch_switch_mode = -1, ch = -1, ch_switch_cnt = -1;
- int ch_offset = -1;
- u8 bwmode;
- struct ieee80211_info_element *ie;
- RTW_INFO(FUNC_NDEV_FMT" from "MAC_FMT"\n",
- FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(psta->cmn.mac_addr));
- for_each_ie(ie, ies, ies_len) {
- if (ie->id == WLAN_EID_CHANNEL_SWITCH) {
- ch_switch_mode = ie->data[0];
- ch = ie->data[1];
- ch_switch_cnt = ie->data[2];
- RTW_INFO("ch_switch_mode:%d, ch:%d, ch_switch_cnt:%d\n",
- ch_switch_mode, ch, ch_switch_cnt);
- } else if (ie->id == WLAN_EID_SECONDARY_CHANNEL_OFFSET) {
- ch_offset = secondary_ch_offset_to_hal_ch_offset(ie->data[0]);
- RTW_INFO("ch_offset:%d\n", ch_offset);
- }
- }
- if (ch == -1)
- return _SUCCESS;
- if (ch_offset == -1)
- bwmode = mlmeext->cur_bwmode;
- else
- bwmode = (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) ?
- CHANNEL_WIDTH_20 : CHANNEL_WIDTH_40;
- ch_offset = (ch_offset == -1) ? mlmeext->cur_ch_offset : ch_offset;
- /* todo:
- * 1. the decision of channel switching
- * 2. things after channel switching
- */
- ret = rtw_set_chbw_cmd(padapter, ch, bwmode, ch_offset, 0);
- }
- exit:
- return ret;
- }
- unsigned int on_action_spct(_adapter *padapter, union recv_frame *precv_frame)
- {
- unsigned int ret = _FAIL;
- struct sta_info *psta = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint frame_len = precv_frame->u.hdr.len;
- u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
- u8 category;
- u8 action;
- psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (!psta)
- goto exit;
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
- goto exit;
- action = frame_body[1];
- RTW_INFO(FUNC_ADPT_FMT" action:%u\n", FUNC_ADPT_ARG(padapter), action);
- switch (action) {
- case RTW_WLAN_ACTION_SPCT_MSR_REQ:
- case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
- case RTW_WLAN_ACTION_SPCT_TPC_REQ:
- case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
- break;
- case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
- #ifdef CONFIG_SPCT_CH_SWITCH
- ret = on_action_spct_ch_switch(padapter, psta
- , frame_body + 2, frame_len - (frame_body - pframe) - 2);
- #elif defined(CONFIG_DFS)
- if (MLME_IS_STA(padapter) && MLME_IS_ASOC(padapter)) {
- process_csa_ie(padapter
- , frame_body + 2, frame_len - (frame_body - pframe) - 2);
- }
- #endif
- break;
- default:
- break;
- }
- exit:
- return ret;
- }
- unsigned int OnAction_qos(_adapter *padapter, union recv_frame *precv_frame)
- {
- return _SUCCESS;
- }
- unsigned int OnAction_dls(_adapter *padapter, union recv_frame *precv_frame)
- {
- return _SUCCESS;
- }
- #ifdef CONFIG_RTW_WNM
- unsigned int on_action_wnm(_adapter *adapter, union recv_frame *rframe)
- {
- unsigned int ret = _FAIL;
- struct sta_info *sta = NULL;
- struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
- struct sta_priv *stapriv = &(adapter->stapriv);
- u8 *frame = rframe->u.hdr.rx_data;
- u32 frame_len = rframe->u.hdr.len;
- u8 *frame_body = (u8 *)(frame + sizeof(struct rtw_ieee80211_hdr_3addr));
- u32 frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr);
- u8 category, action;
- int cnt = 0;
- char msg[16];
- sta = rtw_get_stainfo(stapriv, get_addr2_ptr(frame));
- if (!sta)
- goto exit;
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_WNM)
- goto exit;
- action = frame_body[1];
- switch (action) {
- #ifdef CONFIG_RTW_80211R
- case RTW_WLAN_ACTION_WNM_BTM_REQ:
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) {
- RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_REQ recv.\n");
- rtw_wnm_process_btm_req(adapter, frame_body, frame_body_len);
- }
- ret = _SUCCESS;
- break;
- #endif
- default:
- #ifdef CONFIG_IOCTL_CFG80211
- cnt += sprintf((msg + cnt), "ACT_WNM %u", action);
- rtw_cfg80211_rx_action(adapter, rframe, msg);
- #endif
- ret = _SUCCESS;
- break;
- }
- exit:
- return ret;
- }
- #endif /* CONFIG_RTW_WNM */
- /**
- * rtw_rx_ampdu_size - Get the target RX AMPDU buffer size for the specific @adapter
- * @adapter: the adapter to get target RX AMPDU buffer size
- *
- * Returns: the target RX AMPDU buffer size
- */
- u8 rtw_rx_ampdu_size(_adapter *adapter)
- {
- u8 size;
- HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
- #ifdef CONFIG_BT_COEXIST
- if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(adapter) == _TRUE) {
- size = rtw_btcoex_GetAMPDUSize(adapter);
- goto exit;
- }
- #endif
- /* for scan */
- if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE)
- && !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE)
- && adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size != RX_AMPDU_SIZE_INVALID
- ) {
- size = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size;
- goto exit;
- }
- /* default value based on max_rx_ampdu_factor */
- if (adapter->driver_rx_ampdu_factor != 0xFF)
- max_rx_ampdu_factor = (HT_CAP_AMPDU_FACTOR)adapter->driver_rx_ampdu_factor;
- else
- rtw_hal_get_def_var(adapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
-
- /* In Maximum A-MPDU Length Exponent subfield of A-MPDU Parameters field of HT Capabilities element,
- the unit of max_rx_ampdu_factor are octets. 8K, 16K, 32K, 64K is right.
- But the buffer size subfield of Block Ack Parameter Set field in ADDBA action frame indicates
- the number of buffers available for this particular TID. Each buffer is equal to max. size of
- MSDU or AMSDU.
- The size variable means how many MSDUs or AMSDUs, it's not Kbytes.
- */
- if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
- size = 64;
- else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
- size = 32;
- else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
- size = 16;
- else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
- size = 8;
- else
- size = 64;
- exit:
- if (size > 127)
- size = 127;
- return size;
- }
- /**
- * rtw_rx_ampdu_is_accept - Get the permission if RX AMPDU should be set up for the specific @adapter
- * @adapter: the adapter to get the permission if RX AMPDU should be set up
- *
- * Returns: accept or not
- */
- bool rtw_rx_ampdu_is_accept(_adapter *adapter)
- {
- bool accept;
- if (adapter->fix_rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID) {
- accept = adapter->fix_rx_ampdu_accept;
- goto exit;
- }
- #ifdef CONFIG_BT_COEXIST
- if (rtw_btcoex_IsBTCoexRejectAMPDU(adapter) == _TRUE) {
- accept = _FALSE;
- goto exit;
- }
- #endif
- /* for scan */
- if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE)
- && !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE)
- && adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID
- ) {
- accept = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept;
- goto exit;
- }
- /* default value for other cases */
- accept = adapter->mlmeextpriv.mlmext_info.bAcceptAddbaReq;
- exit:
- return accept;
- }
- /**
- * rtw_rx_ampdu_set_size - Set the target RX AMPDU buffer size for the specific @adapter and specific @reason
- * @adapter: the adapter to set target RX AMPDU buffer size
- * @size: the target RX AMPDU buffer size to set
- * @reason: reason for the target RX AMPDU buffer size setting
- *
- * Returns: whether the target RX AMPDU buffer size is changed
- */
- bool rtw_rx_ampdu_set_size(_adapter *adapter, u8 size, u8 reason)
- {
- bool is_adj = _FALSE;
- struct mlme_ext_priv *mlmeext;
- struct mlme_ext_info *mlmeinfo;
- mlmeext = &adapter->mlmeextpriv;
- mlmeinfo = &mlmeext->mlmext_info;
- if (reason == RX_AMPDU_DRV_FIXED) {
- if (adapter->fix_rx_ampdu_size != size) {
- adapter->fix_rx_ampdu_size = size;
- is_adj = _TRUE;
- RTW_INFO(FUNC_ADPT_FMT" fix_rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size);
- }
- } else if (reason == RX_AMPDU_DRV_SCAN) {
- struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res;
- if (ss->rx_ampdu_size != size) {
- ss->rx_ampdu_size = size;
- is_adj = _TRUE;
- RTW_INFO(FUNC_ADPT_FMT" ss.rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size);
- }
- }
- return is_adj;
- }
- /**
- * rtw_rx_ampdu_set_accept - Set the permission if RX AMPDU should be set up for the specific @adapter and specific @reason
- * @adapter: the adapter to set if RX AMPDU should be set up
- * @accept: if RX AMPDU should be set up
- * @reason: reason for the permission if RX AMPDU should be set up
- *
- * Returns: whether the permission if RX AMPDU should be set up is changed
- */
- bool rtw_rx_ampdu_set_accept(_adapter *adapter, u8 accept, u8 reason)
- {
- bool is_adj = _FALSE;
- struct mlme_ext_priv *mlmeext;
- struct mlme_ext_info *mlmeinfo;
- mlmeext = &adapter->mlmeextpriv;
- mlmeinfo = &mlmeext->mlmext_info;
- if (reason == RX_AMPDU_DRV_FIXED) {
- if (adapter->fix_rx_ampdu_accept != accept) {
- adapter->fix_rx_ampdu_accept = accept;
- is_adj = _TRUE;
- RTW_INFO(FUNC_ADPT_FMT" fix_rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept);
- }
- } else if (reason == RX_AMPDU_DRV_SCAN) {
- if (adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != accept) {
- adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept = accept;
- is_adj = _TRUE;
- RTW_INFO(FUNC_ADPT_FMT" ss.rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept);
- }
- }
- return is_adj;
- }
- /**
- * rx_ampdu_apply_sta_tid - Apply RX AMPDU setting to the specific @sta and @tid
- * @adapter: the adapter to which @sta belongs
- * @sta: the sta to be checked
- * @tid: the tid to be checked
- * @accept: the target permission if RX AMPDU should be set up
- * @size: the target RX AMPDU buffer size
- *
- * Returns:
- * 0: no canceled
- * 1: canceled by no permission
- * 2: canceled by different buffer size
- * 3: canceled by potential mismatched status
- *
- * Blocking function, may sleep
- */
- u8 rx_ampdu_apply_sta_tid(_adapter *adapter, struct sta_info *sta, u8 tid, u8 accept, u8 size)
- {
- u8 ret = 0;
- struct recv_reorder_ctrl *reorder_ctl = &sta->recvreorder_ctrl[tid];
- if (reorder_ctl->enable == _FALSE) {
- if (reorder_ctl->ampdu_size != RX_AMPDU_SIZE_INVALID) {
- send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 1);
- ret = 3;
- }
- goto exit;
- }
- if (accept == _FALSE) {
- send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0);
- ret = 1;
- } else if (reorder_ctl->ampdu_size != size) {
- send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0);
- ret = 2;
- }
- exit:
- return ret;
- }
- u8 rx_ampdu_size_sta_limit(_adapter *adapter, struct sta_info *sta)
- {
- u8 sz_limit = 0xFF;
- #ifdef CONFIG_80211N_HT
- struct registry_priv *regsty = adapter_to_regsty(adapter);
- struct mlme_priv *mlme = &adapter->mlmepriv;
- struct mlme_ext_info *mlmeinfo = &adapter->mlmeextpriv.mlmext_info;
- s8 nss = -1;
- u8 bw = rtw_min(sta->cmn.bw_mode, adapter->mlmeextpriv.cur_bwmode);
- #ifdef CONFIG_80211AC_VHT
- if (is_supported_vht(sta->wireless_mode)) {
- nss = rtw_min(rtw_vht_mcsmap_to_nss(mlme->vhtpriv.vht_mcs_map)
- , rtw_vht_mcsmap_to_nss(sta->vhtpriv.vht_mcs_map));
- } else
- #endif
- if (is_supported_ht(sta->wireless_mode)) {
- nss = rtw_min(rtw_ht_mcsset_to_nss(mlmeinfo->HT_caps.u.HT_cap_element.MCS_rate)
- , rtw_ht_mcsset_to_nss(sta->htpriv.ht_cap.supp_mcs_set));
- }
- if (nss >= 1)
- sz_limit = regsty->rx_ampdu_sz_limit_by_nss_bw[nss - 1][bw];
- #endif /* CONFIG_80211N_HT */
- return sz_limit;
- }
- /**
- * rx_ampdu_apply_sta - Apply RX AMPDU setting to the specific @sta
- * @adapter: the adapter to which @sta belongs
- * @sta: the sta to be checked
- * @accept: the target permission if RX AMPDU should be set up
- * @size: the target RX AMPDU buffer size
- *
- * Returns: number of the RX AMPDU assciation canceled for applying current target setting
- *
- * Blocking function, may sleep
- */
- u8 rx_ampdu_apply_sta(_adapter *adapter, struct sta_info *sta, u8 accept, u8 size)
- {
- u8 change_cnt = 0;
- int i;
- for (i = 0; i < TID_NUM; i++) {
- if (rx_ampdu_apply_sta_tid(adapter, sta, i, accept, size) != 0)
- change_cnt++;
- }
- return change_cnt;
- }
- /**
- * rtw_rx_ampdu_apply - Apply the current target RX AMPDU setting for the specific @adapter
- * @adapter: the adapter to be applied
- *
- * Returns: number of the RX AMPDU assciation canceled for applying current target setting
- */
- u16 rtw_rx_ampdu_apply(_adapter *adapter)
- {
- u16 adj_cnt = 0;
- struct sta_info *sta;
- u8 accept = rtw_rx_ampdu_is_accept(adapter);
- u8 size;
- if (adapter->fix_rx_ampdu_size != RX_AMPDU_SIZE_INVALID)
- size = adapter->fix_rx_ampdu_size;
- else
- size = rtw_rx_ampdu_size(adapter);
- if (MLME_IS_STA(adapter)) {
- sta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv));
- if (sta) {
- u8 sta_size = size;
- if (adapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID)
- sta_size = rtw_min(size, rx_ampdu_size_sta_limit(adapter, sta));
- adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, sta_size);
- }
- /* TODO: TDLS peer */
- } else if (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) {
- _irqL irqL;
- _list *phead, *plist;
- u8 peer_num = 0;
- char peers[NUM_STA];
- struct sta_priv *pstapriv = &adapter->stapriv;
- int i;
- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- phead = &pstapriv->asoc_list;
- plist = get_next(phead);
- while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
- int stainfo_offset;
- sta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
- plist = get_next(plist);
- stainfo_offset = rtw_stainfo_offset(pstapriv, sta);
- if (stainfo_offset_valid(stainfo_offset))
- peers[peer_num++] = stainfo_offset;
- }
- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
- for (i = 0; i < peer_num; i++) {
- sta = rtw_get_stainfo_by_offset(pstapriv, peers[i]);
- if (sta) {
- u8 sta_size = size;
- if (adapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID)
- sta_size = rtw_min(size, rx_ampdu_size_sta_limit(adapter, sta));
- adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, sta_size);
- }
- }
- }
- /* TODO: ADHOC */
- return adj_cnt;
- }
- unsigned int OnAction_back(_adapter *padapter, union recv_frame *precv_frame)
- {
- u8 *addr;
- struct sta_info *psta = NULL;
- struct recv_reorder_ctrl *preorder_ctrl;
- unsigned char *frame_body;
- unsigned char category, action;
- unsigned short tid, status, reason_code = 0;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 *pframe = precv_frame->u.hdr.rx_data;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct registry_priv *pregpriv = &padapter->registrypriv;
- #ifdef CONFIG_80211N_HT
- RTW_INFO("%s\n", __FUNCTION__);
- /* check RA matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
- return _SUCCESS;
- #if 0
- /* check A1 matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))
- return _SUCCESS;
- #endif
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
- return _SUCCESS;
- addr = get_addr2_ptr(pframe);
- psta = rtw_get_stainfo(pstapriv, addr);
- if (psta == NULL)
- return _SUCCESS;
- frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
- category = frame_body[0];
- if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */
- #ifdef CONFIG_TDLS
- if ((psta->tdls_sta_state & TDLS_LINKED_STATE) &&
- (psta->htpriv.ht_option == _TRUE) &&
- (psta->htpriv.ampdu_enable == _TRUE))
- RTW_INFO("Recv [%s] from direc link\n", __FUNCTION__);
- else
- #endif /* CONFIG_TDLS */
- if (!pmlmeinfo->HT_enable)
- return _SUCCESS;
- action = frame_body[1];
- RTW_INFO("%s, action=%d\n", __FUNCTION__, action);
- switch (action) {
- case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
- _rtw_memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
- /* process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
- process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
- break;
- case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
- /* status = frame_body[3] | (frame_body[4] << 8); */ /* endian issue */
- status = RTW_GET_LE16(&frame_body[3]);
- tid = ((frame_body[5] >> 2) & 0x7);
- if (status == 0) {
- /* successful */
- RTW_INFO("agg_enable for TID=%d\n", tid);
- psta->htpriv.agg_enable_bitmap |= 1 << tid;
- psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
- /* amsdu in ampdu */
- if (pregpriv->tx_ampdu_amsdu == 0)
- psta->htpriv.tx_amsdu_enable = _FALSE;
- else if (pregpriv->tx_ampdu_amsdu == 1)
- psta->htpriv.tx_amsdu_enable = _TRUE;
- else {
- if (frame_body[5] & 1)
- psta->htpriv.tx_amsdu_enable = _TRUE;
- }
- } else
- psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
- if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
- RTW_INFO("%s alive check - rx ADDBA response\n", __func__);
- psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
- psta->expire_to = pstapriv->expire_to;
- psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
- }
- /* RTW_INFO("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */
- break;
- case RTW_WLAN_ACTION_DELBA: /* DELBA */
- if ((frame_body[3] & BIT(3)) == 0) {
- psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
- psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
- /* reason_code = frame_body[4] | (frame_body[5] << 8); */
- reason_code = RTW_GET_LE16(&frame_body[4]);
- } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
- tid = (frame_body[3] >> 4) & 0x0F;
- preorder_ctrl = &psta->recvreorder_ctrl[tid];
- preorder_ctrl->enable = _FALSE;
- preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;
- }
- RTW_INFO("%s(): DELBA: %x(%x)\n", __FUNCTION__, pmlmeinfo->agg_enable_bitmap, reason_code);
- /* todo: how to notify the host while receiving DELETE BA */
- break;
- default:
- break;
- }
- }
- #endif /* CONFIG_80211N_HT */
- return _SUCCESS;
- }
- #ifdef CONFIG_P2P
- int get_reg_classes_full_count(struct p2p_channels *channel_list)
- {
- int cnt = 0;
- int i;
- for (i = 0; i < channel_list->reg_classes; i++)
- cnt += channel_list->reg_class[i].channels;
- return cnt;
- }
- void issue_p2p_GO_request(_adapter *padapter, u8 *raddr)
- {
- struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);
- unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
- u8 action = P2P_PUB_ACTION_ACTION;
- u32 p2poui = cpu_to_be32(P2POUI);
- u8 oui_subtype = P2P_GO_NEGO_REQ;
- u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
- u8 wpsielen = 0, p2pielen = 0;
- u16 len_channellist_attr = 0;
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- RTW_INFO("[%s] In\n", __FUNCTION__);
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
- pwdinfo->negotiation_dialog_token = 1; /* Initialize the dialog value */
- pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
- /* WPS Section */
- wpsielen = 0;
- /* WPS OUI */
- *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
- wpsielen += 4;
- /* WPS version */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
- /* Device Password ID */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
- wpsielen += 2;
- /* Value: */
- if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
- else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
- else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
- wpsielen += 2;
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
- /* P2P IE Section. */
- /* P2P OUI */
- p2pielen = 0;
- p2pie[p2pielen++] = 0x50;
- p2pie[p2pielen++] = 0x6F;
- p2pie[p2pielen++] = 0x9A;
- p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
- /* Commented by Albert 20110306 */
- /* According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
- /* 1. P2P Capability */
- /* 2. Group Owner Intent */
- /* 3. Configuration Timeout */
- /* 4. Listen Channel */
- /* 5. Extended Listen Timing */
- /* 6. Intended P2P Interface Address */
- /* 7. Channel List */
- /* 8. P2P Device Info */
- /* 9. Operating Channel */
- /* P2P Capability */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- /* Device Capability Bitmap, 1 byte */
- p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
- /* Group Capability Bitmap, 1 byte */
- if (pwdinfo->persistent_supported)
- p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
- else
- p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
- /* Group Owner Intent */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
- p2pielen += 2;
- /* Value: */
- /* Todo the tie breaker bit. */
- p2pie[p2pielen++] = ((pwdinfo->intent << 1) & 0xFE);
- /* Configuration Timeout */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
- /* Listen Channel */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Operating Class */
- p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */
- /* Extended Listen Timing ATTR */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
- p2pielen += 2;
- /* Value: */
- /* Availability Period */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
- p2pielen += 2;
- /* Availability Interval */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
- p2pielen += 2;
- /* Intended P2P Interface Address */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
- p2pielen += 2;
- /* Value: */
- _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* Channel List */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
- /* Length: */
- /* Country String(3) */
- /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
- /* + number of channels in all classes */
- len_channellist_attr = 3
- + (1 + 1) * (u16)(ch_list->reg_classes)
- + get_reg_classes_full_count(ch_list);
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);
- else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #endif
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Channel Entry List */
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
- u8 union_ch = rtw_mi_get_union_chan(padapter);
- /* Operating Class */
- if (union_ch > 14) {
- if (union_ch >= 149)
- p2pie[p2pielen++] = 0x7c;
- else
- p2pie[p2pielen++] = 0x73;
- } else
- p2pie[p2pielen++] = 0x51;
- /* Number of Channels */
- /* Just support 1 channel and this channel is AP's channel */
- p2pie[p2pielen++] = 1;
- /* Channel List */
- p2pie[p2pielen++] = union_ch;
- } else
- #endif /* CONFIG_CONCURRENT_MODE */
- {
- int i, j;
- for (j = 0; j < ch_list->reg_classes; j++) {
- /* Operating Class */
- p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;
- /* Number of Channels */
- p2pie[p2pielen++] = ch_list->reg_class[j].channels;
- /* Channel List */
- for (i = 0; i < ch_list->reg_class[j].channels; i++)
- p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];
- }
- }
- /* Device Info */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
- /* Length: */
- /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
- /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- /* P2P Device Address */
- _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* Config Method */
- /* This field should be big endian. Noted by P2P specification. */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
- p2pielen += 2;
- /* Primary Device Type */
- /* Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
- p2pielen += 2;
- /* OUI */
- *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
- p2pielen += 4;
- /* Sub Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
- p2pielen += 2;
- /* Number of Secondary Device Types */
- p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
- /* Device Name */
- /* Type: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
- p2pielen += 2;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
- p2pielen += pwdinfo->device_name_len;
- /* Operating Channel */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Operating Class */
- if (pwdinfo->operating_channel <= 14) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x51;
- } else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x73;
- } else {
- /* Operating Class */
- p2pie[p2pielen++] = 0x7c;
- }
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
- #ifdef CONFIG_WFD
- wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- void issue_p2p_GO_response(_adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)
- {
- struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);
- unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
- u8 action = P2P_PUB_ACTION_ACTION;
- u32 p2poui = cpu_to_be32(P2POUI);
- u8 oui_subtype = P2P_GO_NEGO_RESP;
- u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
- u8 p2pielen = 0;
- uint wpsielen = 0;
- u16 wps_devicepassword_id = 0x0000;
- uint wps_devicepassword_id_len = 0;
- u16 len_channellist_attr = 0;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- RTW_INFO("[%s] In, result = %d\n", __FUNCTION__, result);
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
- pwdinfo->negotiation_dialog_token = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
- pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
- /* Commented by Albert 20110328 */
- /* Try to get the device password ID from the WPS IE of group negotiation request frame */
- /* WiFi Direct test plan 5.1.15 */
- rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
- rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);
- wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
- _rtw_memset(wpsie, 0x00, 255);
- wpsielen = 0;
- /* WPS Section */
- wpsielen = 0;
- /* WPS OUI */
- *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
- wpsielen += 4;
- /* WPS version */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
- /* Device Password ID */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
- wpsielen += 2;
- /* Value: */
- if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
- else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
- else
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
- wpsielen += 2;
- /* Commented by Kurt 20120113 */
- /* If some device wants to do p2p handshake without sending prov_disc_req */
- /* We have to get peer_req_cm from here. */
- if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
- if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
- _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
- else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
- _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
- else
- _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
- }
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
- /* P2P IE Section. */
- /* P2P OUI */
- p2pielen = 0;
- p2pie[p2pielen++] = 0x50;
- p2pie[p2pielen++] = 0x6F;
- p2pie[p2pielen++] = 0x9A;
- p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
- /* Commented by Albert 20100908 */
- /* According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
- /* 1. Status */
- /* 2. P2P Capability */
- /* 3. Group Owner Intent */
- /* 4. Configuration Timeout */
- /* 5. Operating Channel */
- /* 6. Intended P2P Interface Address */
- /* 7. Channel List */
- /* 8. Device Info */
- /* 9. Group ID ( Only GO ) */
- /* ToDo: */
- /* P2P Status */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_STATUS;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
- p2pielen += 2;
- /* Value: */
- p2pie[p2pielen++] = result;
- /* P2P Capability */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- /* Device Capability Bitmap, 1 byte */
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
- /* Commented by Albert 2011/03/08 */
- /* According to the P2P specification */
- /* if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */
- p2pie[p2pielen++] = 0;
- } else {
- /* Be group owner or meet the error case */
- p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
- }
- /* Group Capability Bitmap, 1 byte */
- if (pwdinfo->persistent_supported)
- p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
- else
- p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
- /* Group Owner Intent */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
- p2pielen += 2;
- /* Value: */
- if (pwdinfo->peer_intent & 0x01) {
- /* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
- p2pie[p2pielen++] = (pwdinfo->intent << 1);
- } else {
- /* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
- p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
- }
- /* Configuration Timeout */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
- /* Operating Channel */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Operating Class */
- if (pwdinfo->operating_channel <= 14) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x51;
- } else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x73;
- } else {
- /* Operating Class */
- p2pie[p2pielen++] = 0x7c;
- }
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
- /* Intended P2P Interface Address */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
- p2pielen += 2;
- /* Value: */
- _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* Channel List */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
- /* Country String(3) */
- /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
- /* + number of channels in all classes */
- len_channellist_attr = 3
- + (1 + 1) * (u16)ch_list->reg_classes
- + get_reg_classes_full_count(ch_list);
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);
- else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #endif
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Channel Entry List */
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
- u8 union_chan = rtw_mi_get_union_chan(padapter);
- /*Operating Class*/
- if (union_chan > 14) {
- if (union_chan >= 149)
- p2pie[p2pielen++] = 0x7c;
- else
- p2pie[p2pielen++] = 0x73;
- } else
- p2pie[p2pielen++] = 0x51;
- /* Number of Channels
- Just support 1 channel and this channel is AP's channel*/
- p2pie[p2pielen++] = 1;
- /*Channel List*/
- p2pie[p2pielen++] = union_chan;
- } else
- #endif /* CONFIG_CONCURRENT_MODE */
- {
- int i, j;
- for (j = 0; j < ch_list->reg_classes; j++) {
- /* Operating Class */
- p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;
- /* Number of Channels */
- p2pie[p2pielen++] = ch_list->reg_class[j].channels;
- /* Channel List */
- for (i = 0; i < ch_list->reg_class[j].channels; i++)
- p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];
- }
- }
- /* Device Info */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
- /* Length: */
- /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
- /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- /* P2P Device Address */
- _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* Config Method */
- /* This field should be big endian. Noted by P2P specification. */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
- p2pielen += 2;
- /* Primary Device Type */
- /* Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
- p2pielen += 2;
- /* OUI */
- *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
- p2pielen += 4;
- /* Sub Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
- p2pielen += 2;
- /* Number of Secondary Device Types */
- p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
- /* Device Name */
- /* Type: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
- p2pielen += 2;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
- p2pielen += pwdinfo->device_name_len;
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- /* Group ID Attribute */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
- p2pielen += 2;
- /* Value: */
- /* p2P Device Address */
- _rtw_memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* SSID */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
- p2pielen += pwdinfo->nego_ssidlen;
- }
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
- #ifdef CONFIG_WFD
- wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- void issue_p2p_GO_confirm(_adapter *padapter, u8 *raddr, u8 result)
- {
- unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
- u8 action = P2P_PUB_ACTION_ACTION;
- u32 p2poui = cpu_to_be32(P2POUI);
- u8 oui_subtype = P2P_GO_NEGO_CONF;
- u8 p2pie[255] = { 0x00 };
- u8 p2pielen = 0;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- RTW_INFO("[%s] In\n", __FUNCTION__);
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
- /* P2P IE Section. */
- /* P2P OUI */
- p2pielen = 0;
- p2pie[p2pielen++] = 0x50;
- p2pie[p2pielen++] = 0x6F;
- p2pie[p2pielen++] = 0x9A;
- p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
- /* Commented by Albert 20110306 */
- /* According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
- /* 1. Status */
- /* 2. P2P Capability */
- /* 3. Operating Channel */
- /* 4. Channel List */
- /* 5. Group ID ( if this WiFi is GO ) */
- /* P2P Status */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_STATUS;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
- p2pielen += 2;
- /* Value: */
- p2pie[p2pielen++] = result;
- /* P2P Capability */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- /* Device Capability Bitmap, 1 byte */
- p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
- /* Group Capability Bitmap, 1 byte */
- if (pwdinfo->persistent_supported)
- p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
- else
- p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
- /* Operating Channel */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
- if (pwdinfo->peer_operating_ch <= 14) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x51;
- } else if ((pwdinfo->peer_operating_ch >= 36) && (pwdinfo->peer_operating_ch <= 48)) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x73;
- } else {
- /* Operating Class */
- p2pie[p2pielen++] = 0x7c;
- }
- p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
- } else {
- if (pwdinfo->operating_channel <= 14) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x51;
- } else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x73;
- } else {
- /* Operating Class */
- p2pie[p2pielen++] = 0x7c;
- }
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */
- }
- /* Channel List */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
- *(u16 *)(p2pie + p2pielen) = 6;
- p2pielen += 2;
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Value: */
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
- if (pwdinfo->peer_operating_ch <= 14) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x51;
- } else if ((pwdinfo->peer_operating_ch >= 36) && (pwdinfo->peer_operating_ch <= 48)) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x73;
- } else {
- /* Operating Class */
- p2pie[p2pielen++] = 0x7c;
- }
- p2pie[p2pielen++] = 1;
- p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
- } else {
- if (pwdinfo->operating_channel <= 14) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x51;
- } else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {
- /* Operating Class */
- p2pie[p2pielen++] = 0x73;
- } else {
- /* Operating Class */
- p2pie[p2pielen++] = 0x7c;
- }
- /* Channel Number */
- p2pie[p2pielen++] = 1;
- p2pie[p2pielen++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */
- }
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- /* Group ID Attribute */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
- p2pielen += 2;
- /* Value: */
- /* p2P Device Address */
- _rtw_memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* SSID */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
- p2pielen += pwdinfo->nego_ssidlen;
- }
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
- #ifdef CONFIG_WFD
- wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- void issue_p2p_invitation_request(_adapter *padapter, u8 *raddr)
- {
- struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);
- unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
- u8 action = P2P_PUB_ACTION_ACTION;
- u32 p2poui = cpu_to_be32(P2POUI);
- u8 oui_subtype = P2P_INVIT_REQ;
- u8 p2pie[255] = { 0x00 };
- u8 p2pielen = 0;
- u8 dialogToken = 3;
- u16 len_channellist_attr = 0;
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
- /* P2P IE Section. */
- /* P2P OUI */
- p2pielen = 0;
- p2pie[p2pielen++] = 0x50;
- p2pie[p2pielen++] = 0x6F;
- p2pie[p2pielen++] = 0x9A;
- p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
- /* Commented by Albert 20101011 */
- /* According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
- /* 1. Configuration Timeout */
- /* 2. Invitation Flags */
- /* 3. Operating Channel ( Only GO ) */
- /* 4. P2P Group BSSID ( Should be included if I am the GO ) */
- /* 5. Channel List */
- /* 6. P2P Group ID */
- /* 7. P2P Device Info */
- /* Configuration Timeout */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
- /* Invitation Flags */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
- p2pielen += 2;
- /* Value: */
- p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
- /* Operating Channel */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Operating Class */
- if (pwdinfo->invitereq_info.operating_ch <= 14)
- p2pie[p2pielen++] = 0x51;
- else if ((pwdinfo->invitereq_info.operating_ch >= 36) && (pwdinfo->invitereq_info.operating_ch <= 48))
- p2pie[p2pielen++] = 0x73;
- else
- p2pie[p2pielen++] = 0x7c;
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch; /* operating channel number */
- if (_rtw_memcmp(adapter_mac_addr(padapter), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
- /* P2P Group BSSID */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
- p2pielen += 2;
- /* Value: */
- /* P2P Device Address for GO */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
- p2pielen += ETH_ALEN;
- }
- /* Channel List */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
- /* Length: */
- /* Country String(3) */
- /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
- /* + number of channels in all classes */
- len_channellist_attr = 3
- + (1 + 1) * (u16)ch_list->reg_classes
- + get_reg_classes_full_count(ch_list);
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);
- else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #endif
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Channel Entry List */
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
- u8 union_ch = rtw_mi_get_union_chan(padapter);
- /* Operating Class */
- if (union_ch > 14) {
- if (union_ch >= 149)
- p2pie[p2pielen++] = 0x7c;
- else
- p2pie[p2pielen++] = 0x73;
- } else
- p2pie[p2pielen++] = 0x51;
- /* Number of Channels */
- /* Just support 1 channel and this channel is AP's channel */
- p2pie[p2pielen++] = 1;
- /* Channel List */
- p2pie[p2pielen++] = union_ch;
- } else
- #endif /* CONFIG_CONCURRENT_MODE */
- {
- int i, j;
- for (j = 0; j < ch_list->reg_classes; j++) {
- /* Operating Class */
- p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;
- /* Number of Channels */
- p2pie[p2pielen++] = ch_list->reg_class[j].channels;
- /* Channel List */
- for (i = 0; i < ch_list->reg_class[j].channels; i++)
- p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];
- }
- }
- /* P2P Group ID */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
- p2pielen += 2;
- /* Value: */
- /* P2P Device Address for GO */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* SSID */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);
- p2pielen += pwdinfo->invitereq_info.ssidlen;
- /* Device Info */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
- /* Length: */
- /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
- /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- /* P2P Device Address */
- _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* Config Method */
- /* This field should be big endian. Noted by P2P specification. */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
- p2pielen += 2;
- /* Primary Device Type */
- /* Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
- p2pielen += 2;
- /* OUI */
- *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
- p2pielen += 4;
- /* Sub Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
- p2pielen += 2;
- /* Number of Secondary Device Types */
- p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
- /* Device Name */
- /* Type: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
- p2pielen += 2;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
- p2pielen += pwdinfo->device_name_len;
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
- #ifdef CONFIG_WFD
- wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- void issue_p2p_invitation_response(_adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)
- {
- struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);
- unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
- u8 action = P2P_PUB_ACTION_ACTION;
- u32 p2poui = cpu_to_be32(P2POUI);
- u8 oui_subtype = P2P_INVIT_RESP;
- u8 p2pie[255] = { 0x00 };
- u8 p2pielen = 0;
- u16 len_channellist_attr = 0;
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
- /* P2P IE Section. */
- /* P2P OUI */
- p2pielen = 0;
- p2pie[p2pielen++] = 0x50;
- p2pie[p2pielen++] = 0x6F;
- p2pie[p2pielen++] = 0x9A;
- p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
- /* Commented by Albert 20101005 */
- /* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
- /* 1. Status */
- /* 2. Configuration Timeout */
- /* 3. Operating Channel ( Only GO ) */
- /* 4. P2P Group BSSID ( Only GO ) */
- /* 5. Channel List */
- /* P2P Status */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_STATUS;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
- p2pielen += 2;
- /* Value: */
- /* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
- /* Sent the event receiving the P2P Invitation Req frame to DMP UI. */
- /* DMP had to compare the MAC address to find out the profile. */
- /* So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
- /* If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
- /* to NB to rebuild the persistent group. */
- p2pie[p2pielen++] = status_code;
- /* Configuration Timeout */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
- p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
- if (status_code == P2P_STATUS_SUCCESS) {
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- /* The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
- /* In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
- /* First one is operating channel attribute. */
- /* Second one is P2P Group BSSID attribute. */
- /* Operating Channel */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Operating Class */
- p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
- /* P2P Group BSSID */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
- p2pielen += 2;
- /* Value: */
- /* P2P Device Address for GO */
- _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
- p2pielen += ETH_ALEN;
- }
- /* Channel List */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
- /* Length: */
- /* Country String(3) */
- /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
- /* + number of channels in all classes */
- len_channellist_attr = 3
- + (1 + 1) * (u16)ch_list->reg_classes
- + get_reg_classes_full_count(ch_list);
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);
- else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #else
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
- #endif
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Channel Entry List */
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
- u8 union_ch = rtw_mi_get_union_chan(padapter);
- /* Operating Class */
- if (union_ch > 14) {
- if (union_ch >= 149)
- p2pie[p2pielen++] = 0x7c;
- else
- p2pie[p2pielen++] = 0x73;
- } else
- p2pie[p2pielen++] = 0x51;
- /* Number of Channels */
- /* Just support 1 channel and this channel is AP's channel */
- p2pie[p2pielen++] = 1;
- /* Channel List */
- p2pie[p2pielen++] = union_ch;
- } else
- #endif /* CONFIG_CONCURRENT_MODE */
- {
- int i, j;
- for (j = 0; j < ch_list->reg_classes; j++) {
- /* Operating Class */
- p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;
- /* Number of Channels */
- p2pie[p2pielen++] = ch_list->reg_class[j].channels;
- /* Channel List */
- for (i = 0; i < ch_list->reg_class[j].channels; i++)
- p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];
- }
- }
- }
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
- #ifdef CONFIG_WFD
- wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- void issue_p2p_provision_request(_adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
- {
- unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
- u8 action = P2P_PUB_ACTION_ACTION;
- u8 dialogToken = 1;
- u32 p2poui = cpu_to_be32(P2POUI);
- u8 oui_subtype = P2P_PROVISION_DISC_REQ;
- u8 wpsie[100] = { 0x00 };
- u8 wpsielen = 0;
- u32 p2pielen = 0;
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- RTW_INFO("[%s] In\n", __FUNCTION__);
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
- p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);
- pframe += p2pielen;
- pattrib->pktlen += p2pielen;
- wpsielen = 0;
- /* WPS OUI */
- *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
- wpsielen += 4;
- /* WPS version */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
- /* Config Method */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
- wpsielen += 2;
- /* Value: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
- wpsielen += 2;
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
- #ifdef CONFIG_WFD
- wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)
- {
- u8 i, match_result = 0;
- RTW_INFO("[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
- peermacaddr[0], peermacaddr[1], peermacaddr[2], peermacaddr[3], peermacaddr[4], peermacaddr[5]);
- for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
- RTW_INFO("[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
- profileinfo->peermac[0], profileinfo->peermac[1], profileinfo->peermac[2], profileinfo->peermac[3], profileinfo->peermac[4], profileinfo->peermac[5]);
- if (_rtw_memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
- match_result = 1;
- RTW_INFO("[%s] Match!\n", __FUNCTION__);
- break;
- }
- }
- return match_result ;
- }
- void issue_probersp_p2p(_adapter *padapter, unsigned char *da)
- {
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- unsigned char *mac;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- /* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */
- u16 beacon_interval = 100;
- u16 capInfo = 0;
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- u8 wpsie[255] = { 0x00 };
- u32 wpsielen = 0, p2pielen = 0;
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- #ifdef CONFIG_INTEL_WIDI
- u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
- #endif /* CONFIG_INTEL_WIDI */
- /* RTW_INFO("%s\n", __FUNCTION__); */
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- if (IS_CCK_RATE(pattrib->rate)) {
- /* force OFDM 6M rate */
- pattrib->rate = MGN_6M;
- pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G);
- }
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- mac = adapter_mac_addr(padapter);
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
- /* Use the device address for BSSID field. */
- _rtw_memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(fctrl, WIFI_PROBERSP);
- pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = pattrib->hdrlen;
- pframe += pattrib->hdrlen;
- /* timestamp will be inserted by hardware */
- pframe += 8;
- pattrib->pktlen += 8;
- /* beacon interval: 2 bytes */
- _rtw_memcpy(pframe, (unsigned char *) &beacon_interval, 2);
- pframe += 2;
- pattrib->pktlen += 2;
- /* capability info: 2 bytes */
- /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
- capInfo |= cap_ShortPremble;
- capInfo |= cap_ShortSlot;
- _rtw_memcpy(pframe, (unsigned char *) &capInfo, 2);
- pframe += 2;
- pattrib->pktlen += 2;
- /* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
- /* supported rates... */
- /* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
- /* DS parameter set */
- pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {
- if (pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL) {
- /* WPS IE */
- _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
- pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
- pframe += pmlmepriv->wps_probe_resp_ie_len;
- /* P2P IE */
- _rtw_memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len);
- pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
- pframe += pmlmepriv->p2p_probe_resp_ie_len;
- }
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- /* Todo: WPS IE */
- /* Noted by Albert 20100907 */
- /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */
- wpsielen = 0;
- /* WPS OUI */
- *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
- wpsielen += 4;
- /* WPS version */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
- #ifdef CONFIG_INTEL_WIDI
- /* Commented by Kurt */
- /* Appended WiDi info. only if we did issued_probereq_widi(), and then we saved ven. ext. in pmlmepriv->sa_ext. */
- if (_rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE
- || pmlmepriv->num_p2p_sdt != 0) {
- /* Sec dev type */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SEC_DEV_TYPE_LIST);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
- wpsielen += 2;
- /* Value: */
- /* Category ID */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_DISPLAYS);
- wpsielen += 2;
- /* OUI */
- *(u32 *)(wpsie + wpsielen) = cpu_to_be32(INTEL_DEV_TYPE_OUI);
- wpsielen += 4;
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_WIDI_CONSUMER_SINK);
- wpsielen += 2;
- if (_rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE) {
- /* Vendor Extension */
- _rtw_memcpy(wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN);
- wpsielen += L2SDTA_SERVICE_VE_LEN;
- }
- }
- #endif /* CONFIG_INTEL_WIDI */
- /* WiFi Simple Config State */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */
- /* Response Type */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
- /* UUID-E */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
- wpsielen += 2;
- /* Value: */
- if (pwdinfo->external_uuid == 0) {
- _rtw_memset(wpsie + wpsielen, 0x0, 16);
- _rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN);
- } else
- _rtw_memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10);
- wpsielen += 0x10;
- /* Manufacturer */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
- wpsielen += 2;
- /* Value: */
- _rtw_memcpy(wpsie + wpsielen, "Realtek", 7);
- wpsielen += 7;
- /* Model Name */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
- wpsielen += 2;
- /* Value: */
- _rtw_memcpy(wpsie + wpsielen, "8192CU", 6);
- wpsielen += 6;
- /* Model Number */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = 0x31; /* character 1 */
- /* Serial Number */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
- wpsielen += 2;
- /* Value: */
- _rtw_memcpy(wpsie + wpsielen, "123456" , ETH_ALEN);
- wpsielen += ETH_ALEN;
- /* Primary Device Type */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
- wpsielen += 2;
- /* Value: */
- /* Category ID */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
- wpsielen += 2;
- /* OUI */
- *(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
- wpsielen += 4;
- /* Sub Category ID */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
- wpsielen += 2;
- /* Device Name */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
- wpsielen += 2;
- /* Value: */
- _rtw_memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
- wpsielen += pwdinfo->device_name_len;
- /* Config Method */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
- wpsielen += 2;
- /* Value: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
- wpsielen += 2;
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
- p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
- pframe += p2pielen;
- pattrib->pktlen += p2pielen;
- }
- #ifdef CONFIG_WFD
- wfdielen = rtw_append_probe_resp_wfd_ie(padapter, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack)
- {
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- unsigned char *mac;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
- u16 wpsielen = 0, p2pielen = 0;
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- goto exit;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- if (IS_CCK_RATE(pattrib->rate)) {
- /* force OFDM 6M rate */
- pattrib->rate = MGN_6M;
- pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G);
- }
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- mac = adapter_mac_addr(padapter);
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- if (da) {
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
- } else {
- if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
- /* This two flags will be set when this is only the P2P client mode. */
- _rtw_memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
- } else {
- /* broadcast probe request frame */
- _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
- }
- }
- _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_PROBEREQ);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
- pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
- else
- pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
- /* Use the OFDM rate in the P2P probe request frame. ( 6(B), 9(B), 12(B), 24(B), 36, 48, 54 ) */
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {
- if (pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL) {
- /* WPS IE */
- _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
- pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
- pframe += pmlmepriv->wps_probe_req_ie_len;
- /* P2P IE */
- _rtw_memcpy(pframe, pmlmepriv->p2p_probe_req_ie, pmlmepriv->p2p_probe_req_ie_len);
- pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
- pframe += pmlmepriv->p2p_probe_req_ie_len;
- }
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- /* WPS IE */
- /* Noted by Albert 20110221 */
- /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */
- wpsielen = 0;
- /* WPS OUI */
- *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
- wpsielen += 4;
- /* WPS version */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
- wpsielen += 2;
- /* Value: */
- wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
- if (pmlmepriv->wps_probe_req_ie == NULL) {
- /* UUID-E */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
- wpsielen += 2;
- /* Value: */
- if (pwdinfo->external_uuid == 0) {
- _rtw_memset(wpsie + wpsielen, 0x0, 16);
- _rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN);
- } else
- _rtw_memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10);
- wpsielen += 0x10;
- /* Config Method */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
- wpsielen += 2;
- /* Value: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
- wpsielen += 2;
- }
- /* Device Name */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
- wpsielen += 2;
- /* Value: */
- _rtw_memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
- wpsielen += pwdinfo->device_name_len;
- /* Primary Device Type */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
- wpsielen += 2;
- /* Value: */
- /* Category ID */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
- wpsielen += 2;
- /* OUI */
- *(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
- wpsielen += 4;
- /* Sub Category ID */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
- wpsielen += 2;
- /* Device Password ID */
- /* Type: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
- wpsielen += 2;
- /* Length: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
- wpsielen += 2;
- /* Value: */
- *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); /* Registrar-specified */
- wpsielen += 2;
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
- /* P2P OUI */
- p2pielen = 0;
- p2pie[p2pielen++] = 0x50;
- p2pie[p2pielen++] = 0x6F;
- p2pie[p2pielen++] = 0x9A;
- p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
- /* Commented by Albert 20110221 */
- /* According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
- /* 1. P2P Capability */
- /* 2. P2P Device ID if this probe request wants to find the specific P2P device */
- /* 3. Listen Channel */
- /* 4. Extended Listen Timing */
- /* 5. Operating Channel if this WiFi is working as the group owner now */
- /* P2P Capability */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- /* Device Capability Bitmap, 1 byte */
- p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
- /* Group Capability Bitmap, 1 byte */
- if (pwdinfo->persistent_supported)
- p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
- else
- p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
- /* Listen Channel */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Operating Class */
- p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->listen_channel; /* listen channel */
- /* Extended Listen Timing */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
- p2pielen += 2;
- /* Value: */
- /* Availability Period */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
- p2pielen += 2;
- /* Availability Interval */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
- p2pielen += 2;
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- /* Operating Channel (if this WiFi is working as the group owner now) */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
- p2pielen += 2;
- /* Value: */
- /* Country String */
- p2pie[p2pielen++] = 'X';
- p2pie[p2pielen++] = 'X';
- /* The third byte should be set to 0x04. */
- /* Described in the "Operating Channel Attribute" section. */
- p2pie[p2pielen++] = 0x04;
- /* Operating Class */
- p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
- /* Channel Number */
- p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
- }
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
- }
- #ifdef CONFIG_WFD
- wfdielen = rtw_append_probe_req_wfd_ie(padapter, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- if (wait_ack)
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
- exit:
- return ret;
- }
- inline void issue_probereq_p2p(_adapter *adapter, u8 *da)
- {
- _issue_probereq_p2p(adapter, da, _FALSE);
- }
- /*
- * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- * try_cnt means the maximal TX count to try
- */
- int issue_probereq_p2p_ex(_adapter *adapter, u8 *da, int try_cnt, int wait_ms)
- {
- int ret;
- int i = 0;
- systime start = rtw_get_current_time();
- do {
- ret = _issue_probereq_p2p(adapter, da, wait_ms > 0 ? _TRUE : _FALSE);
- i++;
- if (RTW_CANNOT_RUN(adapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- goto exit;
- #endif
- }
- if (try_cnt && wait_ms) {
- if (da)
- RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(adapter), MAC_ARG(da), rtw_get_oper_ch(adapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- else
- RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- #endif /* CONFIG_P2P */
- s32 rtw_action_public_decache(union recv_frame *rframe, u8 token_offset)
- {
- _adapter *adapter = rframe->u.hdr.adapter;
- struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
- u8 *frame = rframe->u.hdr.rx_data;
- u16 seq_ctrl = ((rframe->u.hdr.attrib.seq_num & 0xffff) << 4) | (rframe->u.hdr.attrib.frag_num & 0xf);
- u8 token = *(rframe->u.hdr.rx_data + sizeof(struct rtw_ieee80211_hdr_3addr) + token_offset);
- if (GetRetry(frame)) {
- if ((seq_ctrl == mlmeext->action_public_rxseq)
- && (token == mlmeext->action_public_dialog_token)
- ) {
- RTW_INFO(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x, token:%d\n",
- FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
- return _FAIL;
- }
- }
- /* TODO: per sta seq & token */
- mlmeext->action_public_rxseq = seq_ctrl;
- mlmeext->action_public_dialog_token = token;
- return _SUCCESS;
- }
- unsigned int on_action_public_p2p(union recv_frame *precv_frame)
- {
- _adapter *padapter = precv_frame->u.hdr.adapter;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint len = precv_frame->u.hdr.len;
- u8 *frame_body;
- #ifdef CONFIG_P2P
- u8 *p2p_ie;
- u32 p2p_ielen;
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- u8 result = P2P_STATUS_SUCCESS;
- u8 empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- u8 *merged_p2pie = NULL;
- u32 merged_p2p_ielen = 0;
- #endif /* CONFIG_P2P */
- frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
- #ifdef CONFIG_P2P
- _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211)
- rtw_cfg80211_rx_p2p_action_public(padapter, precv_frame);
- else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- /* Do nothing if the driver doesn't enable the P2P function. */
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
- return _SUCCESS;
- len -= sizeof(struct rtw_ieee80211_hdr_3addr);
- switch (frame_body[6]) { /* OUI Subtype */
- case P2P_GO_NEGO_REQ: {
- RTW_INFO("[%s] Got GO Nego Req Frame\n", __FUNCTION__);
- _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
- rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {
- /* Commented by Albert 20110526 */
- /* In this case, this means the previous nego fail doesn't be reset yet. */
- _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
- /* Restore the previous p2p state */
- rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
- RTW_INFO("[%s] Restore the previous p2p state to %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo));
- }
- #ifdef CONFIG_CONCURRENT_MODE
- if (rtw_mi_buddy_check_fwstate(padapter, _FW_LINKED))
- _cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
- #endif /* CONFIG_CONCURRENT_MODE */
- /* Commented by Kurt 20110902 */
- /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
- if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
- rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
- /* Commented by Kurt 20120113 */
- /* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
- if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
- _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN);
- result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
- issue_p2p_GO_response(padapter, get_addr2_ptr(pframe), frame_body, len, result);
- #ifdef CONFIG_INTEL_WIDI
- if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) {
- padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
- _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
- intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
- }
- #endif /* CONFIG_INTEL_WIDI */
- /* Commented by Albert 20110718 */
- /* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
- #ifdef CONFIG_CONCURRENT_MODE
- /* Commented by Albert 20120107 */
- _set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
- #else /* CONFIG_CONCURRENT_MODE */
- _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
- #endif /* CONFIG_CONCURRENT_MODE */
- break;
- }
- case P2P_GO_NEGO_RESP: {
- RTW_INFO("[%s] Got GO Nego Resp Frame\n", __FUNCTION__);
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
- /* Commented by Albert 20110425 */
- /* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
- _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
- pwdinfo->nego_req_info.benable = _FALSE;
- result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);
- issue_p2p_GO_confirm(pwdinfo->padapter, get_addr2_ptr(pframe), result);
- if (P2P_STATUS_SUCCESS == result) {
- if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
- pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
- #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
- pwdinfo->p2p_info.operation_ch[1] = 1; /* Check whether GO is operating in channel 1; */
- pwdinfo->p2p_info.operation_ch[2] = 6; /* Check whether GO is operating in channel 6; */
- pwdinfo->p2p_info.operation_ch[3] = 11; /* Check whether GO is operating in channel 11; */
- #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
- pwdinfo->p2p_info.scan_op_ch_only = 1;
- _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
- }
- }
- /* Reset the dialog token for group negotiation frames. */
- pwdinfo->negotiation_dialog_token = 1;
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
- _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
- } else
- RTW_INFO("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __FUNCTION__);
- break;
- }
- case P2P_GO_NEGO_CONF: {
- RTW_INFO("[%s] Got GO Nego Confirm Frame\n", __FUNCTION__);
- result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);
- if (P2P_STATUS_SUCCESS == result) {
- if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
- pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
- #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
- pwdinfo->p2p_info.operation_ch[1] = 1; /* Check whether GO is operating in channel 1; */
- pwdinfo->p2p_info.operation_ch[2] = 6; /* Check whether GO is operating in channel 6; */
- pwdinfo->p2p_info.operation_ch[3] = 11; /* Check whether GO is operating in channel 11; */
- #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
- pwdinfo->p2p_info.scan_op_ch_only = 1;
- _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
- }
- }
- break;
- }
- case P2P_INVIT_REQ: {
- /* Added by Albert 2010/10/05 */
- /* Received the P2P Invite Request frame. */
- RTW_INFO("[%s] Got invite request frame!\n", __FUNCTION__);
- p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
- if (p2p_ie) {
- /* Parse the necessary information from the P2P Invitation Request frame. */
- /* For example: The MAC address of sending this P2P Invitation Request frame. */
- u32 attr_contentlen = 0;
- u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
- struct group_id_info group_id;
- u8 invitation_flag = 0;
- merged_p2p_ielen = rtw_get_p2p_merged_ies_len(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_);
- merged_p2pie = rtw_zmalloc(merged_p2p_ielen + 2); /* 2 is for EID and Length */
- if (merged_p2pie == NULL) {
- RTW_INFO("[%s] Malloc p2p ie fail\n", __FUNCTION__);
- goto exit;
- }
- _rtw_memset(merged_p2pie, 0x00, merged_p2p_ielen);
- merged_p2p_ielen = rtw_p2p_merge_ies(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, merged_p2pie);
- rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
- if (attr_contentlen) {
- rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
- /* Commented by Albert 20120510 */
- /* Copy to the pwdinfo->p2p_peer_interface_addr. */
- /* So that the WFD UI ( or Sigma ) can get the peer interface address by using the following command. */
- /* #> iwpriv wlan0 p2p_get peer_ifa */
- /* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
- if (attr_contentlen) {
- RTW_INFO("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
- pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
- pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
- pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
- }
- if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {
- /* Re-invoke the persistent group. */
- _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
- rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *) &group_id, &attr_contentlen);
- if (attr_contentlen) {
- if (_rtw_memcmp(group_id.go_device_addr, adapter_mac_addr(padapter), ETH_ALEN)) {
- /* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
- status_code = P2P_STATUS_SUCCESS;
- } else {
- /* The p2p device sending this p2p invitation request wants to be the persistent GO. */
- if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {
- u8 operatingch_info[5] = { 0x00 };
- if (rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info,
- &attr_contentlen)) {
- if (rtw_chset_search_ch(adapter_to_chset(padapter), (u32)operatingch_info[4]) >= 0) {
- /* The operating channel is acceptable for this device. */
- pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];
- #ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
- pwdinfo->rx_invitereq_info.operation_ch[1] = 1; /* Check whether GO is operating in channel 1; */
- pwdinfo->rx_invitereq_info.operation_ch[2] = 6; /* Check whether GO is operating in channel 6; */
- pwdinfo->rx_invitereq_info.operation_ch[3] = 11; /* Check whether GO is operating in channel 11; */
- #endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */
- pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
- _set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
- status_code = P2P_STATUS_SUCCESS;
- } else {
- /* The operating channel isn't supported by this device. */
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
- status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
- _set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
- }
- } else {
- /* Commented by Albert 20121130 */
- /* Intel will use the different P2P IE to store the operating channel information */
- /* Workaround for Intel WiDi 3.5 */
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
- status_code = P2P_STATUS_SUCCESS;
- }
- } else {
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
- #ifdef CONFIG_INTEL_WIDI
- _rtw_memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN);
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
- #endif /* CONFIG_INTEL_WIDI */
- status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
- }
- }
- } else {
- RTW_INFO("[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__);
- status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
- }
- } else {
- /* Received the invitation to join a P2P group. */
- _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
- rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *) &group_id, &attr_contentlen);
- if (attr_contentlen) {
- if (_rtw_memcmp(group_id.go_device_addr, adapter_mac_addr(padapter), ETH_ALEN)) {
- /* In this case, the GO can't be myself. */
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
- status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
- } else {
- /* The p2p device sending this p2p invitation request wants to join an existing P2P group */
- /* Commented by Albert 2012/06/28 */
- /* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
- /* The peer device address should be the destination address for the provisioning discovery request. */
- /* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
- /* The peer interface address should be the address for WPS mac address */
- _rtw_memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN);
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
- status_code = P2P_STATUS_SUCCESS;
- }
- } else {
- RTW_INFO("[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__);
- status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
- }
- }
- } else {
- RTW_INFO("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __FUNCTION__);
- status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
- }
- RTW_INFO("[%s] status_code = %d\n", __FUNCTION__, status_code);
- pwdinfo->inviteresp_info.token = frame_body[7];
- issue_p2p_invitation_response(padapter, get_addr2_ptr(pframe), pwdinfo->inviteresp_info.token, status_code);
- _set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
- }
- #ifdef CONFIG_INTEL_WIDI
- if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) {
- padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
- _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
- intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
- }
- #endif /* CONFIG_INTEL_WIDI */
- break;
- }
- case P2P_INVIT_RESP: {
- u8 attr_content = 0x00;
- u32 attr_contentlen = 0;
- RTW_INFO("[%s] Got invite response frame!\n", __FUNCTION__);
- _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
- p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
- if (p2p_ie) {
- rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
- if (attr_contentlen == 1) {
- RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);
- pwdinfo->invitereq_info.benable = _FALSE;
- if (attr_content == P2P_STATUS_SUCCESS) {
- if (_rtw_memcmp(pwdinfo->invitereq_info.go_bssid, adapter_mac_addr(padapter), ETH_ALEN))
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
- else
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
- } else {
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
- }
- } else {
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
- }
- } else {
- rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
- }
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))
- _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
- break;
- }
- case P2P_DEVDISC_REQ:
- process_p2p_devdisc_req(pwdinfo, pframe, len);
- break;
- case P2P_DEVDISC_RESP:
- process_p2p_devdisc_resp(pwdinfo, pframe, len);
- break;
- case P2P_PROVISION_DISC_REQ:
- RTW_INFO("[%s] Got Provisioning Discovery Request Frame\n", __FUNCTION__);
- process_p2p_provdisc_req(pwdinfo, pframe, len);
- _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN);
- /* 20110902 Kurt */
- /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
- if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
- rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
- _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
- #ifdef CONFIG_INTEL_WIDI
- if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) {
- padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
- _cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
- intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
- }
- #endif /* CONFIG_INTEL_WIDI */
- break;
- case P2P_PROVISION_DISC_RESP:
- /* Commented by Albert 20110707 */
- /* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
- RTW_INFO("[%s] Got Provisioning Discovery Response Frame\n", __FUNCTION__);
- /* Commented by Albert 20110426 */
- /* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
- _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
- process_p2p_provdisc_resp(pwdinfo, pframe);
- _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
- break;
- }
- }
- exit:
- if (merged_p2pie)
- rtw_mfree(merged_p2pie, merged_p2p_ielen + 2);
- #endif /* CONFIG_P2P */
- return _SUCCESS;
- }
- unsigned int on_action_public_vendor(union recv_frame *precv_frame)
- {
- unsigned int ret = _FAIL;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
- if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE) {
- if (rtw_action_public_decache(precv_frame, 7) == _FAIL)
- goto exit;
- if (!hal_chk_wl_func(precv_frame->u.hdr.adapter, WL_FUNC_MIRACAST))
- rtw_rframe_del_wfd_ie(precv_frame, 8);
- ret = on_action_public_p2p(precv_frame);
- }
- exit:
- return ret;
- }
- unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
- {
- unsigned int ret = _FAIL;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
- u8 token;
- _adapter *adapter = precv_frame->u.hdr.adapter;
- int cnt = 0;
- char msg[64];
- token = frame_body[2];
- if (rtw_action_public_decache(precv_frame, 2) == _FAIL)
- goto exit;
- #ifdef CONFIG_IOCTL_CFG80211
- cnt += sprintf((msg + cnt), "%s(token:%u)", action_public_str(action), token);
- rtw_cfg80211_rx_action(adapter, precv_frame, msg);
- #endif
- ret = _SUCCESS;
- exit:
- return ret;
- }
- unsigned int on_action_public(_adapter *padapter, union recv_frame *precv_frame)
- {
- unsigned int ret = _FAIL;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint frame_len = precv_frame->u.hdr.len;
- u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
- u8 category, action;
- /* check RA matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
- goto exit;
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_PUBLIC)
- goto exit;
- action = frame_body[1];
- switch (action) {
- case ACT_PUBLIC_BSSCOEXIST:
- #ifdef CONFIG_80211N_HT
- #ifdef CONFIG_AP_MODE
- /*20/40 BSS Coexistence Management frame is a Public Action frame*/
- if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
- rtw_process_public_act_bsscoex(padapter, pframe, frame_len);
- #endif /*CONFIG_AP_MODE*/
- #endif /*CONFIG_80211N_HT*/
- break;
- case ACT_PUBLIC_VENDOR:
- ret = on_action_public_vendor(precv_frame);
- break;
- default:
- ret = on_action_public_default(precv_frame, action);
- break;
- }
- exit:
- return ret;
- }
- #if defined(CONFIG_RTW_WNM) || defined(CONFIG_RTW_80211K)
- static u8 rtw_wnm_nb_elem_parsing(
- u8* pdata, u32 data_len, u8 from_btm,
- u32 *nb_rpt_num, u8 *nb_rpt_is_same,
- struct roam_nb_info *pnb, struct wnm_btm_cant *pcandidates)
- {
- u8 bfound = _FALSE, ret = _SUCCESS;
- u8 *ptr, *pend, *op;
- u32 elem_len, subelem_len, op_len;
- u32 i, nb_rpt_entries = 0;
- struct nb_rpt_hdr *pie;
- struct wnm_btm_cant *pcandidate;
- if ((!pdata) || (!pnb))
- return _FAIL;
- if ((from_btm) && (!pcandidates))
- return _FAIL;
- ptr = pdata;
- pend = ptr + data_len;
- elem_len = data_len;
- subelem_len = (u32)*(pdata+1);
- for (i=0; i < RTW_MAX_NB_RPT_NUM; i++) {
- if (((ptr + 7) > pend) || (elem_len < subelem_len))
- break;
- if (*ptr != 0x34) {
- RTW_ERR("WNM: invalid data(0x%2x)!\n", *ptr);
- ret = _FAIL;
- break;
- }
- pie = (struct nb_rpt_hdr *)ptr;
- if (from_btm) {
- op = rtw_get_ie((u8 *)(ptr+15),
- WNM_BTM_CAND_PREF_SUBEID,
- &op_len, (subelem_len - 15));
- }
- ptr = (u8 *)(ptr + subelem_len + 2);
- elem_len -= (subelem_len +2);
- subelem_len = *(ptr+1);
- if (from_btm) {
- pcandidate = (pcandidates + i);
- _rtw_memcpy(&pcandidate->nb_rpt, pie, sizeof(struct nb_rpt_hdr));
- if (op && (op_len !=0)) {
- pcandidate->preference = *(op + 2);
- bfound = _TRUE;
- } else
- pcandidate->preference = 0;
- RTW_DBG("WNM: preference check bssid("MAC_FMT
- ") ,bss_info(0x%04X), reg_class(0x%02X), ch(%d),"
- " phy_type(0x%02X), preference(0x%02X)\n",
- MAC_ARG(pcandidate->nb_rpt.bssid), pcandidate->nb_rpt.bss_info,
- pcandidate->nb_rpt.reg_class, pcandidate->nb_rpt.ch_num,
- pcandidate->nb_rpt.phy_type, pcandidate->preference);
- } else {
- if (_rtw_memcmp(&pnb->nb_rpt[i], pie, sizeof(struct nb_rpt_hdr)) == _FALSE)
- *nb_rpt_is_same = _FALSE;
- _rtw_memcpy(&pnb->nb_rpt[i], pie, sizeof(struct nb_rpt_hdr));
- }
- nb_rpt_entries++;
- }
- if (from_btm)
- pnb->preference_en = (bfound)?_TRUE:_FALSE;
- *nb_rpt_num = nb_rpt_entries;
- return ret;
- }
- /* selection sorting based on preference value
- * IN : nb_rpt_entries - candidate num
- * IN/OUT : pcandidates - candidate list
- * return : TRUE - means pcandidates is updated.
- */
- static u8 rtw_wnm_candidates_sorting(
- u32 nb_rpt_entries, struct wnm_btm_cant *pcandidates)
- {
- u8 updated = _FALSE;
- u32 i, j, pos;
- struct wnm_btm_cant swap;
- struct wnm_btm_cant *pcant_1, *pcant_2;
- if ((!nb_rpt_entries) || (!pcandidates))
- return updated;
- for (i=0; i < (nb_rpt_entries - 1); i++) {
- pos = i;
- for (j=(i + 1); j < nb_rpt_entries; j++) {
- pcant_1 = pcandidates+pos;
- pcant_2 = pcandidates+j;
- if ((pcant_1->preference) < (pcant_2->preference))
- pos = j;
- }
- if (pos != i) {
- updated = _TRUE;
- _rtw_memcpy(&swap, (pcandidates+i), sizeof(struct wnm_btm_cant));
- _rtw_memcpy((pcandidates+i), (pcandidates+pos), sizeof(struct wnm_btm_cant));
- _rtw_memcpy((pcandidates+pos), &swap, sizeof(struct wnm_btm_cant));
- }
- }
- return updated;
- }
- static void rtw_wnm_nb_info_update(
- u32 nb_rpt_entries, u8 from_btm,
- struct roam_nb_info *pnb, struct wnm_btm_cant *pcandidates,
- u8 *nb_rpt_is_same)
- {
- u8 is_found;
- u32 i, j;
- struct wnm_btm_cant *pcand;
- if (!pnb)
- return;
- pnb->nb_rpt_ch_list_num = 0;
- for (i=0; i<nb_rpt_entries; i++) {
- is_found = _FALSE;
- if (from_btm) {
- pcand = (pcandidates+i);
- if (_rtw_memcmp(&pnb->nb_rpt[i], &pcand->nb_rpt,
- sizeof(struct nb_rpt_hdr)) == _FALSE)
- *nb_rpt_is_same = _FALSE;
- _rtw_memcpy(&pnb->nb_rpt[i], &pcand->nb_rpt, sizeof(struct nb_rpt_hdr));
- }
- RTW_DBG("WNM: bssid(" MAC_FMT
- ") , bss_info(0x%04X), reg_class(0x%02X), ch_num(%d), phy_type(0x%02X)\n",
- MAC_ARG(pnb->nb_rpt[i].bssid), pnb->nb_rpt[i].bss_info,
- pnb->nb_rpt[i].reg_class, pnb->nb_rpt[i].ch_num,
- pnb->nb_rpt[i].phy_type);
- if (pnb->nb_rpt[i].ch_num == 0)
- continue;
- for (j=0; j<nb_rpt_entries; j++) {
- if (pnb->nb_rpt[i].ch_num == pnb->nb_rpt_ch_list[j].hw_value) {
- is_found = _TRUE;
- break;
- }
- }
-
- if (!is_found) {
- pnb->nb_rpt_ch_list[pnb->nb_rpt_ch_list_num].hw_value = pnb->nb_rpt[i].ch_num;
- pnb->nb_rpt_ch_list_num++;
- }
- }
- }
- static void rtw_wnm_btm_candidate_select(_adapter *padapter)
- {
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);
- struct wlan_network *pnetwork;
- u8 bfound = _FALSE;
- u32 i;
- for (i = 0; i < pnb->last_nb_rpt_entries; i++) {
- pnetwork = rtw_find_network(
- &(pmlmepriv->scanned_queue),
- pnb->nb_rpt[i].bssid);
- if (pnetwork) {
- bfound = _TRUE;
- break;
- }
- }
- if (bfound) {
- _rtw_memcpy(pnb->roam_target_addr, pnb->nb_rpt[i].bssid, ETH_ALEN);
- RTW_INFO("WNM : select btm entry(%d) - %s("MAC_FMT", ch%u) rssi:%d\n"
- , i
- , pnetwork->network.Ssid.Ssid
- , MAC_ARG(pnetwork->network.MacAddress)
- , pnetwork->network.Configuration.DSConfig
- , (int)pnetwork->network.Rssi);
- } else
- _rtw_memset(pnb->roam_target_addr,0, ETH_ALEN);
- }
- u32 rtw_wnm_btm_candidates_survey(
- _adapter *padapter, u8* pframe, u32 elem_len, u8 from_btm)
- {
- struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);
- struct wnm_btm_cant *pcandidate_list = NULL;
- u8 nb_rpt_is_same = _TRUE;
- u32 ret = _FAIL;
- u32 nb_rpt_entries = 0;
- if (from_btm) {
- u32 mlen = sizeof(struct wnm_btm_cant) * RTW_MAX_NB_RPT_NUM;
- pcandidate_list = (struct wnm_btm_cant *)rtw_malloc(mlen);
- if (pcandidate_list == NULL)
- goto exit;
- }
- /*clean the status set last time*/
- _rtw_memset(&pnb->nb_rpt_ch_list, 0, sizeof(pnb->nb_rpt_ch_list));
- pnb->nb_rpt_valid = _FALSE;
- if (!rtw_wnm_nb_elem_parsing(
- pframe, elem_len, from_btm,
- &nb_rpt_entries, &nb_rpt_is_same,
- pnb, pcandidate_list))
- goto exit;
- if (nb_rpt_entries != 0) {
- if ((from_btm) && (rtw_wnm_btm_preference_cap(padapter)))
- rtw_wnm_candidates_sorting(nb_rpt_entries, pcandidate_list);
- rtw_wnm_nb_info_update(
- nb_rpt_entries, from_btm,
- pnb, pcandidate_list, &nb_rpt_is_same);
- }
- RTW_INFO("nb_rpt_is_same = %d, nb_rpt_entries = %d, last_nb_rpt_entries = %d\n",
- nb_rpt_is_same, nb_rpt_entries, pnb->last_nb_rpt_entries);
- if ((nb_rpt_is_same == _TRUE) && (nb_rpt_entries == pnb->last_nb_rpt_entries))
- pnb->nb_rpt_is_same = _TRUE;
- else {
- pnb->nb_rpt_is_same = _FALSE;
- pnb->last_nb_rpt_entries = nb_rpt_entries;
- }
- if ((from_btm) && (nb_rpt_entries != 0))
- rtw_wnm_btm_candidate_select(padapter);
-
- pnb->nb_rpt_valid = _TRUE;
- ret = _SUCCESS;
- exit:
- if (from_btm && pcandidate_list)
- rtw_mfree((u8 *)pcandidate_list, sizeof(struct wnm_btm_cant) * RTW_MAX_NB_RPT_NUM);
-
- return ret;
- }
- #endif
- unsigned int OnAction_ft(_adapter *padapter, union recv_frame *precv_frame)
- {
- #ifdef CONFIG_RTW_80211R
- u32 ret = _FAIL;
- u32 frame_len = 0;
- u8 action_code = 0;
- u8 category = 0;
- u8 *pframe = NULL;
- u8 *pframe_body = NULL;
- u8 sta_addr[ETH_ALEN] = {0};
- u8 *pie = NULL;
- u32 ft_ie_len = 0;
- u32 status_code = 0;
- struct mlme_ext_priv *pmlmeext = NULL;
- struct mlme_ext_info *pmlmeinfo = NULL;
- struct mlme_priv *pmlmepriv = NULL;
- struct wlan_network *proam_target = NULL;
- struct ft_roam_info *pft_roam = NULL;
- _irqL irqL;
- pmlmeext = &(padapter->mlmeextpriv);
- pmlmeinfo = &(pmlmeext->mlmext_info);
- pmlmepriv = &(padapter->mlmepriv);
- pft_roam = &(pmlmepriv->ft_roam);
- pframe = precv_frame->u.hdr.rx_data;
- frame_len = precv_frame->u.hdr.len;
- pframe_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
- category = pframe_body[0];
- if (category != RTW_WLAN_CATEGORY_FT)
- goto exit;
- action_code = pframe_body[1];
- switch (action_code) {
- case RTW_WLAN_ACTION_FT_RSP:
- RTW_INFO("FT: RTW_WLAN_ACTION_FT_RSP recv.\n");
- if (!_rtw_memcmp(adapter_mac_addr(padapter), &pframe_body[2], ETH_ALEN)) {
- RTW_ERR("FT: Unmatched STA MAC Address "MAC_FMT"\n", MAC_ARG(&pframe_body[2]));
- goto exit;
- }
- status_code = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + 14));
- if (status_code != 0) {
- RTW_ERR("FT: WLAN ACTION FT RESPONSE fail, status: %d\n", status_code);
- goto exit;
- }
- if (is_zero_mac_addr(&pframe_body[8]) || is_broadcast_mac_addr(&pframe_body[8])) {
- RTW_ERR("FT: Invalid Target MAC Address "MAC_FMT"\n", MAC_ARG(padapter->mlmepriv.roam_tgt_addr));
- goto exit;
- }
- pie = rtw_get_ie(pframe_body, _MDIE_, &ft_ie_len, frame_len);
- if (pie) {
- if (!_rtw_memcmp(&pft_roam->mdid, pie+2, 2)) {
- RTW_ERR("FT: Invalid MDID\n");
- goto exit;
- }
- }
- rtw_ft_set_status(padapter, RTW_FT_REQUESTED_STA);
- _cancel_timer_ex(&pmlmeext->ft_link_timer);
- /*Disconnect current AP*/
- receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress, WLAN_REASON_ACTIVE_ROAM, _FALSE);
- pft_roam->ft_action_len = frame_len;
- _rtw_memcpy(pft_roam->ft_action, pframe, rtw_min(frame_len, RTW_FT_MAX_IE_SZ));
- ret = _SUCCESS;
- break;
- case RTW_WLAN_ACTION_FT_REQ:
- case RTW_WLAN_ACTION_FT_CONF:
- case RTW_WLAN_ACTION_FT_ACK:
- default:
- RTW_ERR("FT: Unsupported FT Action!\n");
- break;
- }
- exit:
- return ret;
- #else
- return _SUCCESS;
- #endif
- }
- #ifdef CONFIG_RTW_WNM
- u8 rtw_wmn_btm_rsp_reason_decision(_adapter *padapter, u8* req_mode)
- {
- struct recv_priv *precvpriv = &padapter->recvpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 reason = 0;
- if (!rtw_wnm_btm_diff_bss(padapter)) {
- /* Reject - No suitable BSS transition candidates */
- reason = 7;
- goto candidate_remove;
- }
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_chk_flags(padapter, RTW_FT_BTM_ROAM)) {
- /* Accept */
- reason = 0;
- goto under_survey;
- }
- #endif
- if (((*req_mode) & DISASSOC_IMMINENT) == 0) {
- /* Reject - Unspecified reject reason */
- reason = 1;
- goto candidate_remove;
- }
- if (precvpriv->signal_strength_data.avg_val >= pmlmepriv->roam_rssi_threshold) {
- reason = 1;
- goto candidate_remove;
- }
- under_survey:
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
- RTW_INFO("%s reject due to _FW_UNDER_SURVEY\n", __func__);
- reason = 1;
- }
- candidate_remove:
- if (reason !=0)
- rtw_wnm_reset_btm_candidate(&padapter->mlmepriv.nb_info);
- return reason;
- }
- static u32 rtw_wnm_btm_candidates_offset_get(u8* pframe)
- {
- u8 *pos = pframe;
- u32 offset = 0;
- if (!pframe)
- return 0;
- offset += 7;
- pos += offset;
- /* BSS Termination Duration check */
- if (wnm_btm_bss_term_inc(pframe)) {
- offset += 12;
- pos += offset;
- }
- /* Session Information URL check*/
- if (wnm_btm_ess_disassoc_im(pframe)) {
- /*URL length field + URL variable length*/
- offset = 1 + *(pframe + offset);
- pos += offset;
- }
- offset = (pos - pframe);
- return offset;
- }
- static void rtw_wnm_btm_req_hdr_parsing(u8* pframe, struct btm_req_hdr *phdr)
- {
- u8 *pos = pframe;
- u32 offset = 0;
- if (!pframe || !phdr)
- return;
- _rtw_memset(phdr, 0, sizeof(struct btm_req_hdr));
- phdr->req_mode = wnm_btm_req_mode(pframe);
- phdr->disassoc_timer = wnm_btm_disassoc_timer(pframe);
- phdr->validity_interval = wnm_btm_valid_interval(pframe);
- if (wnm_btm_bss_term_inc(pframe)) {
- _rtw_memcpy(&phdr->term_duration,
- wnm_btm_term_duration_offset(pframe),
- sizeof(struct btm_term_duration));
- }
- RTW_DBG("WNM: req_mode(%1x), disassoc_timer(%02x), interval(%x)\n",
- phdr->req_mode, phdr->disassoc_timer, phdr->validity_interval);
- if (wnm_btm_bss_term_inc(pframe))
- RTW_INFO("WNM: tsf(%llx), duration(%2x)\n",
- phdr->term_duration.tsf, phdr->term_duration.duration);
- }
- void rtw_wnm_roam_scan_hdl(void *ctx)
- {
- _adapter *padapter = (_adapter *)ctx;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- if (rtw_is_scan_deny(padapter))
- RTW_INFO("WNM: roam scan would abort by scan_deny!\n");
-
- pmlmepriv->need_to_roam = _TRUE;
- rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM);
- }
- static void rtw_wnm_roam_scan(_adapter *padapter)
- {
- struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);
- if (rtw_is_scan_deny(padapter)) {
- _cancel_timer_ex(&pnb->roam_scan_timer);
- _set_timer(&pnb->roam_scan_timer, 1000);
- } else
- rtw_wnm_roam_scan_hdl((void *)padapter);
- }
- void rtw_wnm_process_btm_req(_adapter *padapter, u8* pframe, u32 frame_len)
- {
- struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);
- struct btm_req_hdr req_hdr;
- u8 *ptr, reason;
- u32 elem_len, offset;
- rtw_wnm_btm_req_hdr_parsing(pframe, &req_hdr);
- offset = rtw_wnm_btm_candidates_offset_get(pframe);
- if ((offset == 0) || ((frame_len - offset) <= 15))
- return;
- ptr = (pframe + offset);
- elem_len = (frame_len - offset);
- rtw_wnm_btm_candidates_survey(padapter, ptr, elem_len, _TRUE);
- reason = rtw_wmn_btm_rsp_reason_decision(padapter, &pframe[3]);
- rtw_wnm_issue_action(padapter,
- RTW_WLAN_ACTION_WNM_BTM_RSP, reason);
- if (reason == 0)
- rtw_wnm_roam_scan(padapter);
- }
- void rtw_wnm_reset_btm_candidate(struct roam_nb_info *pnb)
- {
- pnb->preference_en = _FALSE;
- _rtw_memset(pnb->roam_target_addr, 0, ETH_ALEN);
- }
- void rtw_wnm_reset_btm_state(_adapter *padapter)
- {
- struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);
- pnb->last_nb_rpt_entries = 0;
- pnb->nb_rpt_is_same = _TRUE;
- pnb->nb_rpt_valid = _FALSE;
- pnb->nb_rpt_ch_list_num = 0;
- rtw_wnm_reset_btm_candidate(pnb);
- _rtw_memset(&pnb->nb_rpt, 0, sizeof(pnb->nb_rpt));
- _rtw_memset(&pnb->nb_rpt_ch_list, 0, sizeof(pnb->nb_rpt_ch_list));
- }
- void rtw_wnm_issue_action(_adapter *padapter, u8 action, u8 reason)
- {
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct xmit_frame *pmgntframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- struct pkt_attrib *pattrib;
- u8 category, dialog_token, termination_delay, *pframe;
- u16 *fctrl;
- if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
- return ;
-
- pattrib = &(pmgntframe->attrib);
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, (WLANHDR_OFFSET + TXDESC_OFFSET));
- pframe = (u8 *)(pmgntframe->buf_addr + TXDESC_OFFSET);
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- category = RTW_WLAN_CATEGORY_WNM;
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- switch (action) {
- case RTW_WLAN_ACTION_WNM_BTM_QUERY:
- pframe = rtw_set_fixed_ie(pframe, 1, &(dialog_token), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(reason), &(pattrib->pktlen));
- RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_QUERY sent.\n");
- break;
- case RTW_WLAN_ACTION_WNM_BTM_RSP:
- termination_delay = 0;
- pframe = rtw_set_fixed_ie(pframe, 1, &(dialog_token), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(reason), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(termination_delay), &(pattrib->pktlen));
- if (!is_zero_mac_addr(pmlmepriv->nb_info.roam_target_addr)) {
- pframe = rtw_set_fixed_ie(pframe, 6,
- pmlmepriv->nb_info.roam_target_addr, &(pattrib->pktlen));
- }
- RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_RSP sent. reason = %d\n", reason);
- break;
- default:
- goto exit;
- }
-
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- exit:
- return;
- }
- #endif
- unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame)
- {
- u8 *pframe = precv_frame->u.hdr.rx_data;
- u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
- u8 category, action;
- /* check RA matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
- goto exit;
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_HT)
- goto exit;
- action = frame_body[1];
- switch (action) {
- case RTW_WLAN_ACTION_HT_SM_PS:
- #ifdef CONFIG_80211N_HT
- #ifdef CONFIG_AP_MODE
- if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
- rtw_process_ht_action_smps(padapter, get_addr2_ptr(pframe), frame_body[2]);
- #endif /*CONFIG_AP_MODE*/
- #endif /*CONFIG_80211N_HT*/
- break;
- case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:
- #ifdef CONFIG_BEAMFORMING
- /*RTW_INFO("RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING\n");*/
- rtw_beamforming_get_report_frame(padapter, precv_frame);
- #endif /*CONFIG_BEAMFORMING*/
- break;
- default:
- break;
- }
- exit:
- return _SUCCESS;
- }
- #ifdef CONFIG_IEEE80211W
- unsigned int OnAction_sa_query(_adapter *padapter, union recv_frame *precv_frame)
- {
- u8 *pframe = precv_frame->u.hdr.rx_data;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- u16 tid;
- /* Baron */
- RTW_INFO("OnAction_sa_query\n");
- switch (pframe[WLAN_HDR_A3_LEN + 1]) {
- case 0: /* SA Query req */
- _rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN + 2], sizeof(u16));
- RTW_INFO("OnAction_sa_query request,action=%d, tid=%04x, pframe=%02x-%02x\n"
- , pframe[WLAN_HDR_A3_LEN + 1], tid, pframe[WLAN_HDR_A3_LEN + 2], pframe[WLAN_HDR_A3_LEN + 3]);
- issue_action_SA_Query(padapter, get_addr2_ptr(pframe), 1, tid, IEEE80211W_RIGHT_KEY);
- break;
- case 1: /* SA Query rsp */
- psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
- if (psta != NULL)
- _cancel_timer_ex(&psta->dot11w_expire_timer);
- _rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN + 2], sizeof(u16));
- RTW_INFO("OnAction_sa_query response,action=%d, tid=%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN + 1], tid);
- break;
- default:
- break;
- }
- if (0) {
- int pp;
- printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
- for (pp = 0; pp < pattrib->pkt_len; pp++)
- printk(" %02x ", pframe[pp]);
- printk("\n");
- }
- return _SUCCESS;
- }
- #endif /* CONFIG_IEEE80211W */
- unsigned int on_action_rm(_adapter *padapter, union recv_frame *precv_frame)
- {
- #ifdef CONFIG_RTW_80211K
- return rm_on_action(padapter, precv_frame);
- #else
- return _SUCCESS;
- #endif /* CONFIG_RTW_80211K */
- }
- unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame)
- {
- return _SUCCESS;
- }
- unsigned int OnAction_vht(_adapter *padapter, union recv_frame *precv_frame)
- {
- #ifdef CONFIG_80211AC_VHT
- u8 *pframe = precv_frame->u.hdr.rx_data;
- struct rtw_ieee80211_hdr_3addr *whdr = (struct rtw_ieee80211_hdr_3addr *)pframe;
- u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
- u8 category, action;
- struct sta_info *psta = NULL;
- /* check RA matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
- goto exit;
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_VHT)
- goto exit;
- action = frame_body[1];
- switch (action) {
- case RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING:
- #ifdef CONFIG_BEAMFORMING
- /*RTW_INFO("RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING\n");*/
- rtw_beamforming_get_report_frame(padapter, precv_frame);
- #endif /*CONFIG_BEAMFORMING*/
- break;
- case RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION:
- /* CategoryCode(1) + ActionCode(1) + OpModeNotification(1) */
- /* RTW_INFO("RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION\n"); */
- psta = rtw_get_stainfo(&padapter->stapriv, whdr->addr2);
- if (psta)
- rtw_process_vht_op_mode_notify(padapter, &frame_body[2], psta);
- break;
- case RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT:
- #ifdef CONFIG_BEAMFORMING
- #ifdef RTW_BEAMFORMING_VERSION_2
- rtw_beamforming_get_vht_gid_mgnt_frame(padapter, precv_frame);
- #endif /* RTW_BEAMFORMING_VERSION_2 */
- #endif /* CONFIG_BEAMFORMING */
- break;
- default:
- break;
- }
- exit:
- #endif /* CONFIG_80211AC_VHT */
- return _SUCCESS;
- }
- unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame)
- {
- #ifdef CONFIG_P2P
- u8 *frame_body;
- u8 category, OUI_Subtype, dialogToken = 0;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint len = precv_frame->u.hdr.len;
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- /* check RA matches or not */
- if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
- return _SUCCESS;
- frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
- category = frame_body[0];
- if (category != RTW_WLAN_CATEGORY_P2P)
- return _SUCCESS;
- if (cpu_to_be32(*((u32 *)(frame_body + 1))) != P2POUI)
- return _SUCCESS;
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled
- && pwdinfo->driver_interface == DRIVER_CFG80211
- ) {
- rtw_cfg80211_rx_action_p2p(padapter, precv_frame);
- return _SUCCESS;
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- len -= sizeof(struct rtw_ieee80211_hdr_3addr);
- OUI_Subtype = frame_body[5];
- dialogToken = frame_body[6];
- switch (OUI_Subtype) {
- case P2P_NOTICE_OF_ABSENCE:
- break;
- case P2P_PRESENCE_REQUEST:
- process_p2p_presence_req(pwdinfo, pframe, len);
- break;
- case P2P_PRESENCE_RESPONSE:
- break;
- case P2P_GO_DISC_REQUEST:
- break;
- default:
- break;
- }
- }
- #endif /* CONFIG_P2P */
- return _SUCCESS;
- }
- unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame)
- {
- int i;
- unsigned char category;
- struct action_handler *ptable;
- unsigned char *frame_body;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
- category = frame_body[0];
- for (i = 0; i < sizeof(OnAction_tbl) / sizeof(struct action_handler); i++) {
- ptable = &OnAction_tbl[i];
- if (category == ptable->num)
- ptable->func(padapter, precv_frame);
- }
- return _SUCCESS;
- }
- unsigned int DoReserved(_adapter *padapter, union recv_frame *precv_frame)
- {
- /* RTW_INFO("rcvd mgt frame(%x, %x)\n", (get_frame_sub_type(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */
- return _SUCCESS;
- }
- struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
- {
- struct xmit_frame *pmgntframe;
- struct xmit_buf *pxmitbuf;
- if (once)
- pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
- else
- pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
- if (pmgntframe == NULL) {
- RTW_INFO(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
- goto exit;
- }
- pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
- if (pxmitbuf == NULL) {
- RTW_INFO(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
- rtw_free_xmitframe(pxmitpriv, pmgntframe);
- pmgntframe = NULL;
- goto exit;
- }
- pmgntframe->frame_tag = MGNT_FRAMETAG;
- pmgntframe->pxmitbuf = pxmitbuf;
- pmgntframe->buf_addr = pxmitbuf->pbuf;
- pxmitbuf->priv_data = pmgntframe;
- exit:
- return pmgntframe;
- }
- inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
- {
- return _alloc_mgtxmitframe(pxmitpriv, _FALSE);
- }
- inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv)
- {
- return _alloc_mgtxmitframe(pxmitpriv, _TRUE);
- }
- /****************************************************************************
- Following are some TX fuctions for WiFi MLME
- *****************************************************************************/
- void update_mgnt_tx_rate(_adapter *padapter, u8 rate)
- {
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- pmlmeext->tx_rate = rate;
- /* RTW_INFO("%s(): rate = %x\n",__FUNCTION__, rate); */
- }
- void update_monitor_frame_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
- {
- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
- u8 wireless_mode;
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct sta_info *psta = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- psta = rtw_get_stainfo(pstapriv, pattrib->ra);
- pattrib->hdrlen = 24;
- pattrib->nr_frags = 1;
- pattrib->priority = 7;
- pattrib->mac_id = RTW_DEFAULT_MGMT_MACID;
- pattrib->qsel = QSLT_MGNT;
- pattrib->pktlen = 0;
- if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
- wireless_mode = WIRELESS_11B;
- else
- wireless_mode = WIRELESS_11G;
- pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode);
- #ifdef CONFIG_80211AC_VHT
- if (pHalData->rf_type == RF_1T1R)
- pattrib->raid = RATEID_IDX_VHT_1SS;
- else if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_2T4R)
- pattrib->raid = RATEID_IDX_VHT_2SS;
- else if (pHalData->rf_type == RF_3T3R)
- pattrib->raid = RATEID_IDX_VHT_3SS;
- else
- pattrib->raid = RATEID_IDX_BGN_40M_1SS;
- #endif
- #ifdef CONFIG_80211AC_VHT
- pattrib->rate = MGN_VHT1SS_MCS9;
- #else
- pattrib->rate = MGN_MCS7;
- #endif
- pattrib->encrypt = _NO_PRIVACY_;
- pattrib->bswenc = _FALSE;
- pattrib->qos_en = _FALSE;
- pattrib->ht_en = 1;
- pattrib->bwmode = CHANNEL_WIDTH_20;
- pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pattrib->sgi = _FALSE;
- pattrib->seqnum = pmlmeext->mgnt_seq;
- pattrib->retry_ctrl = _TRUE;
- pattrib->mbssid = 0;
- pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;
- }
- void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
- {
- u8 wireless_mode;
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- /* _rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */
- pattrib->hdrlen = 24;
- pattrib->nr_frags = 1;
- pattrib->priority = 7;
- pattrib->mac_id = RTW_DEFAULT_MGMT_MACID;
- pattrib->qsel = QSLT_MGNT;
- #ifdef CONFIG_MCC_MODE
- update_mcc_mgntframe_attrib(padapter, pattrib);
- #endif
- pattrib->pktlen = 0;
- if (IS_CCK_RATE(pmlmeext->tx_rate))
- wireless_mode = WIRELESS_11B;
- else
- wireless_mode = WIRELESS_11G;
- pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode);
- pattrib->rate = pmlmeext->tx_rate;
- pattrib->encrypt = _NO_PRIVACY_;
- pattrib->bswenc = _FALSE;
- pattrib->qos_en = _FALSE;
- pattrib->ht_en = _FALSE;
- pattrib->bwmode = CHANNEL_WIDTH_20;
- pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pattrib->sgi = _FALSE;
- pattrib->seqnum = pmlmeext->mgnt_seq;
- pattrib->retry_ctrl = _TRUE;
- pattrib->mbssid = 0;
- pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;
- }
- void update_mgntframe_attrib_addr(_adapter *padapter, struct xmit_frame *pmgntframe)
- {
- u8 *pframe;
- struct pkt_attrib *pattrib = &pmgntframe->attrib;
- #if defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY)
- struct sta_info *sta = NULL;
- #endif
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- _rtw_memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
- _rtw_memcpy(pattrib->ta, get_addr2_ptr(pframe), ETH_ALEN);
- #if defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY)
- sta = pattrib->psta;
- if (!sta) {
- sta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
- pattrib->psta = sta;
- }
- #ifdef CONFIG_BEAMFORMING
- if (sta)
- update_attrib_txbf_info(padapter, pattrib, sta);
- #endif
- #endif /* defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY) */
- }
- void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe)
- {
- if (RTW_CANNOT_RUN(padapter)) {
- rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
- rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
- return;
- }
- rtw_hal_mgnt_xmit(padapter, pmgntframe);
- }
- s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
- {
- s32 ret = _FAIL;
- _irqL irqL;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
- struct submit_ctx sctx;
- if (RTW_CANNOT_RUN(padapter)) {
- rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
- rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
- return ret;
- }
- rtw_sctx_init(&sctx, timeout_ms);
- pxmitbuf->sctx = &sctx;
- ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
- if (ret == _SUCCESS)
- ret = rtw_sctx_wait(&sctx, __func__);
- _enter_critical(&pxmitpriv->lock_sctx, &irqL);
- pxmitbuf->sctx = NULL;
- _exit_critical(&pxmitpriv->lock_sctx, &irqL);
- return ret;
- }
- s32 dump_mgntframe_and_wait_ack_timeout(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
- {
- #ifdef CONFIG_XMIT_ACK
- static u8 seq_no = 0;
- s32 ret = _FAIL;
- struct xmit_priv *pxmitpriv = &(GET_PRIMARY_ADAPTER(padapter))->xmitpriv;
- if (RTW_CANNOT_RUN(padapter)) {
- rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
- rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
- return -1;
- }
- _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
- pxmitpriv->ack_tx = _TRUE;
- pxmitpriv->seq_no = seq_no++;
- pmgntframe->ack_report = 1;
- rtw_sctx_init(&(pxmitpriv->ack_tx_ops), timeout_ms);
- if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
- ret = rtw_sctx_wait(&(pxmitpriv->ack_tx_ops), __func__);
- pxmitpriv->ack_tx = _FALSE;
- _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
- return ret;
- #else /* !CONFIG_XMIT_ACK */
- dump_mgntframe(padapter, pmgntframe);
- rtw_msleep_os(50);
- return _SUCCESS;
- #endif /* !CONFIG_XMIT_ACK */
- }
- s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntframe)
- {
- /* In this case, use 500 ms as the default wait_ack timeout */
- return dump_mgntframe_and_wait_ack_timeout(padapter, pmgntframe, 500);
- }
- int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
- {
- u8 *ssid_ie;
- sint ssid_len_ori;
- int len_diff = 0;
- ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
- /* RTW_INFO("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
- if (ssid_ie && ssid_len_ori > 0) {
- switch (hidden_ssid_mode) {
- case 1: {
- u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
- u32 remain_len = 0;
- remain_len = ies_len - (next_ie - ies);
- ssid_ie[1] = 0;
- _rtw_memcpy(ssid_ie + 2, next_ie, remain_len);
- len_diff -= ssid_len_ori;
- break;
- }
- case 2:
- _rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
- break;
- default:
- break;
- }
- }
- return len_diff;
- }
- #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
- u32 rtw_build_vendor_ie(_adapter *padapter , unsigned char *pframe , u8 mgmt_frame_tyte)
- {
- int vendor_ie_num = 0;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- u32 len = 0;
- for (vendor_ie_num = 0 ; vendor_ie_num < WLAN_MAX_VENDOR_IE_NUM ; vendor_ie_num++) {
- if (pmlmepriv->vendor_ielen[vendor_ie_num] > 0 && pmlmepriv->vendor_ie_mask[vendor_ie_num] & mgmt_frame_tyte) {
- _rtw_memcpy(pframe , pmlmepriv->vendor_ie[vendor_ie_num] , pmlmepriv->vendor_ielen[vendor_ie_num]);
- pframe += pmlmepriv->vendor_ielen[vendor_ie_num];
- len += pmlmepriv->vendor_ielen[vendor_ie_num];
- }
- }
- return len;
- }
- #endif
- void issue_beacon(_adapter *padapter, int timeout_ms)
- {
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- unsigned int rate_len;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- #if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
- _irqL irqL;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- #endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
- u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #endif /* CONFIG_P2P */
- /* RTW_INFO("%s\n", __FUNCTION__); */
- #ifdef CONFIG_BCN_ICF
- pmgntframe = rtw_alloc_bcnxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- #else
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- #endif
- {
- RTW_INFO("%s, alloc mgnt frame fail\n", __FUNCTION__);
- return;
- }
- #if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
- _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
- #endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->qsel = QSLT_BEACON;
- #if defined(CONFIG_CONCURRENT_MODE) && (!defined(CONFIG_SWTIMER_BASED_TXBCN))
- if (padapter->hw_port == HW_PORT1)
- pattrib->mbssid = 1;
- #endif
- #ifdef CONFIG_FW_HANDLE_TXBCN
- if (padapter->vap_id != CONFIG_LIMITED_AP_NUM)
- pattrib->mbssid = padapter->vap_id;
- #endif
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
- SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
- /* pmlmeext->mgnt_seq++; */
- set_frame_sub_type(pframe, WIFI_BEACON);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
- /* RTW_INFO("ie len=%d\n", cur_network->IELength); */
- #ifdef CONFIG_P2P
- /* for P2P : Primary Device Type & Device Name */
- u32 wpsielen = 0, insert_len = 0;
- u8 *wpsie = NULL;
- wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
- uint wps_offset, remainder_ielen;
- u8 *premainder_ie, *pframe_wscie;
- wps_offset = (uint)(wpsie - cur_network->IEs);
- premainder_ie = wpsie + wpsielen;
- remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {
- if (pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len > 0) {
- _rtw_memcpy(pframe, cur_network->IEs, wps_offset);
- pframe += wps_offset;
- pattrib->pktlen += wps_offset;
- _rtw_memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
- pframe += pmlmepriv->wps_beacon_ie_len;
- pattrib->pktlen += pmlmepriv->wps_beacon_ie_len;
- /* copy remainder_ie to pframe */
- _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
- pframe += remainder_ielen;
- pattrib->pktlen += remainder_ielen;
- } else {
- _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
- pframe += cur_network->IELength;
- pattrib->pktlen += cur_network->IELength;
- }
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- pframe_wscie = pframe + wps_offset;
- _rtw_memcpy(pframe, cur_network->IEs, wps_offset + wpsielen);
- pframe += (wps_offset + wpsielen);
- pattrib->pktlen += (wps_offset + wpsielen);
- /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
- /* Primary Device Type */
- /* Type: */
- *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
- insert_len += 2;
- /* Length: */
- *(u16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
- insert_len += 2;
- /* Value: */
- /* Category ID */
- *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
- insert_len += 2;
- /* OUI */
- *(u32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
- insert_len += 4;
- /* Sub Category ID */
- *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
- insert_len += 2;
- /* Device Name */
- /* Type: */
- *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
- insert_len += 2;
- /* Length: */
- *(u16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
- insert_len += 2;
- /* Value: */
- _rtw_memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
- insert_len += pwdinfo->device_name_len;
- /* update wsc ie length */
- *(pframe_wscie + 1) = (wpsielen - 2) + insert_len;
- /* pframe move to end */
- pframe += insert_len;
- pattrib->pktlen += insert_len;
- /* copy remainder_ie to pframe */
- _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
- pframe += remainder_ielen;
- pattrib->pktlen += remainder_ielen;
- }
- } else
- #endif /* CONFIG_P2P */
- {
- int len_diff;
- _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
- len_diff = update_hidden_ssid(
- pframe + _BEACON_IE_OFFSET_
- , cur_network->IELength - _BEACON_IE_OFFSET_
- , pmlmeinfo->hidden_ssid_mode
- );
- pframe += (cur_network->IELength + len_diff);
- pattrib->pktlen += (cur_network->IELength + len_diff);
- }
- {
- u8 *wps_ie;
- uint wps_ielen;
- u8 sr = 0;
- wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,
- pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);
- if (wps_ie && wps_ielen > 0)
- rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
- if (sr != 0)
- set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
- else
- _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
- }
- #ifdef CONFIG_RTW_80211K
- pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_,
- sizeof(padapter->rmpriv.rm_en_cap_def),
- padapter->rmpriv.rm_en_cap_def, &pattrib->pktlen);
- #endif
- #ifdef CONFIG_P2P
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- u32 len;
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {
- len = pmlmepriv->p2p_beacon_ie_len;
- if (pmlmepriv->p2p_beacon_ie && len > 0)
- _rtw_memcpy(pframe, pmlmepriv->p2p_beacon_ie, len);
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- len = build_beacon_p2p_ie(pwdinfo, pframe);
- }
- pframe += len;
- pattrib->pktlen += len;
- #ifdef CONFIG_MCC_MODE
- pframe = rtw_hal_mcc_append_go_p2p_ie(padapter, pframe, &pattrib->pktlen);
- #endif /* CONFIG_MCC_MODE*/
- #ifdef CONFIG_WFD
- len = rtw_append_beacon_wfd_ie(padapter, pframe);
- pframe += len;
- pattrib->pktlen += len;
- #endif
- }
- #endif /* CONFIG_P2P */
- #ifdef CONFIG_RTW_REPEATER_SON
- rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen);
- #endif
- #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
- pattrib->pktlen += rtw_build_vendor_ie(padapter , pframe , WIFI_BEACON_VENDOR_IE_BIT);
- #endif
- goto _issue_bcn;
- }
- /* below for ad-hoc mode */
- /* timestamp will be inserted by hardware */
- pframe += 8;
- pattrib->pktlen += 8;
- /* beacon interval: 2 bytes */
- _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
- pframe += 2;
- pattrib->pktlen += 2;
- /* capability info: 2 bytes */
- _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
- pframe += 2;
- pattrib->pktlen += 2;
- /* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
- /* supported rates... */
- rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
- /* DS parameter set */
- pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
- /* if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
- {
- u8 erpinfo = 0;
- u32 ATIMWindow;
- /* IBSS Parameter Set... */
- /* ATIMWindow = cur->Configuration.ATIMWindow; */
- ATIMWindow = 0;
- pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
- /* ERP IE */
- pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
- }
- /* EXTERNDED SUPPORTED RATE */
- if (rate_len > 8)
- pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
- /* todo:HT for adhoc */
- _issue_bcn:
- #if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
- pmlmepriv->update_bcn = _FALSE;
- _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
- #endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
- if ((pattrib->pktlen + TXDESC_SIZE) > MAX_BEACON_LEN) {
- RTW_ERR("beacon frame too large ,len(%d,%d)\n",
- (pattrib->pktlen + TXDESC_SIZE), MAX_BEACON_LEN);
- rtw_warn_on(1);
- return;
- }
- pattrib->last_txcmdsz = pattrib->pktlen;
- /* RTW_INFO("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
- if (timeout_ms > 0)
- dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
- else
- dump_mgntframe(padapter, pmgntframe);
- }
- void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
- {
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- unsigned char *mac, *bssid;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- #if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
- u8 *pwps_ie;
- uint wps_ielen;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- #endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
- unsigned int rate_len;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #endif /* CONFIG_P2P */
- /* RTW_INFO("%s\n", __FUNCTION__); */
- if (da == NULL)
- return;
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- return;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL) {
- RTW_INFO("%s, alloc mgnt frame fail\n", __FUNCTION__);
- return;
- }
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- mac = adapter_mac_addr(padapter);
- bssid = cur_network->MacAddress;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(fctrl, WIFI_PROBERSP);
- pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = pattrib->hdrlen;
- pframe += pattrib->hdrlen;
- if (cur_network->IELength > MAX_IE_SZ)
- return;
- #if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
- pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
- /* inerset & update wps_probe_resp_ie */
- if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
- uint wps_offset, remainder_ielen;
- u8 *premainder_ie;
- wps_offset = (uint)(pwps_ie - cur_network->IEs);
- premainder_ie = pwps_ie + wps_ielen;
- remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
- _rtw_memcpy(pframe, cur_network->IEs, wps_offset);
- pframe += wps_offset;
- pattrib->pktlen += wps_offset;
- wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
- if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {
- _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);
- pframe += wps_ielen + 2;
- pattrib->pktlen += wps_ielen + 2;
- }
- if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
- _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
- pframe += remainder_ielen;
- pattrib->pktlen += remainder_ielen;
- }
- } else {
- _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
- pframe += cur_network->IELength;
- pattrib->pktlen += cur_network->IELength;
- }
- /* retrieve SSID IE from cur_network->Ssid */
- {
- u8 *ssid_ie;
- sint ssid_ielen;
- sint ssid_ielen_diff;
- u8 buf[MAX_IE_SZ];
- u8 *ies = pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr);
- ssid_ie = rtw_get_ie(ies + _FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
- (pframe - ies) - _FIXED_IE_LENGTH_);
- ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
- if (ssid_ie && cur_network->Ssid.SsidLength) {
- uint remainder_ielen;
- u8 *remainder_ie;
- remainder_ie = ssid_ie + 2;
- remainder_ielen = (pframe - remainder_ie);
- if (remainder_ielen > MAX_IE_SZ) {
- RTW_WARN(FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
- remainder_ielen = MAX_IE_SZ;
- }
- _rtw_memcpy(buf, remainder_ie, remainder_ielen);
- _rtw_memcpy(remainder_ie + ssid_ielen_diff, buf, remainder_ielen);
- *(ssid_ie + 1) = cur_network->Ssid.SsidLength;
- _rtw_memcpy(ssid_ie + 2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
- pframe += ssid_ielen_diff;
- pattrib->pktlen += ssid_ielen_diff;
- }
- }
- #ifdef CONFIG_RTW_REPEATER_SON
- rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen);
- #endif
- #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
- pattrib->pktlen += rtw_build_vendor_ie(padapter , pframe , WIFI_PROBERESP_VENDOR_IE_BIT);
- #endif
- } else
- #endif
- {
- /* timestamp will be inserted by hardware */
- pframe += 8;
- pattrib->pktlen += 8;
- /* beacon interval: 2 bytes */
- _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
- pframe += 2;
- pattrib->pktlen += 2;
- /* capability info: 2 bytes */
- _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
- pframe += 2;
- pattrib->pktlen += 2;
- /* below for ad-hoc mode */
- /* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
- /* supported rates... */
- rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
- /* DS parameter set */
- pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- u8 erpinfo = 0;
- u32 ATIMWindow;
- /* IBSS Parameter Set... */
- /* ATIMWindow = cur->Configuration.ATIMWindow; */
- ATIMWindow = 0;
- pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
- /* ERP IE */
- pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
- }
- /* EXTERNDED SUPPORTED RATE */
- if (rate_len > 8)
- pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
- /* todo:HT for adhoc */
- }
- #ifdef CONFIG_RTW_80211K
- pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_,
- sizeof(padapter->rmpriv.rm_en_cap_def),
- padapter->rmpriv.rm_en_cap_def, &pattrib->pktlen);
- #endif
- #ifdef CONFIG_P2P
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
- /* IOT issue, When wifi_spec is not set, send probe_resp with P2P IE even if probe_req has no P2P IE */
- && (is_valid_p2p_probereq || !padapter->registrypriv.wifi_spec)) {
- u32 len;
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {
- /* if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p() */
- len = pmlmepriv->p2p_go_probe_resp_ie_len;
- if (pmlmepriv->p2p_go_probe_resp_ie && len > 0)
- _rtw_memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len);
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- len = build_probe_resp_p2p_ie(pwdinfo, pframe);
- }
- pframe += len;
- pattrib->pktlen += len;
- #ifdef CONFIG_MCC_MODE
- pframe = rtw_hal_mcc_append_go_p2p_ie(padapter, pframe, &pattrib->pktlen);
- #endif /* CONFIG_MCC_MODE*/
- #ifdef CONFIG_WFD
- len = rtw_append_probe_resp_wfd_ie(padapter, pframe);
- pframe += len;
- pattrib->pktlen += len;
- #endif
- }
- #endif /* CONFIG_P2P */
- #ifdef CONFIG_AUTO_AP_MODE
- {
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- RTW_INFO("(%s)\n", __FUNCTION__);
- /* check rc station */
- psta = rtw_get_stainfo(pstapriv, da);
- if (psta && psta->isrc && psta->pid > 0) {
- u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
- u8 RC_INFO[14] = {0};
- /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
- u16 cu_ch = (u16)cur_network->Configuration.DSConfig;
- RTW_INFO("%s, reply rc(pid=0x%x) device "MAC_FMT" in ch=%d\n", __FUNCTION__,
- psta->pid, MAC_ARG(psta->cmn.mac_addr), cu_ch);
- /* append vendor specific ie */
- _rtw_memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));
- _rtw_memcpy(&RC_INFO[4], mac, ETH_ALEN);
- _rtw_memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2);
- _rtw_memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2);
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);
- }
- }
- #endif /* CONFIG_AUTO_AP_MODE */
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- int _issue_probereq(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da, u8 ch, bool append_wps, int wait_ack)
- {
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- unsigned char *mac;
- unsigned char bssrate[NumRates];
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- int bssrate_len = 0;
- u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
- #endif
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- goto exit;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- if ((pwdev_priv->pno_mac_addr[0] != 0xFF)
- && (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE)
- && (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE))
- mac = pwdev_priv->pno_mac_addr;
- else
- #endif
- mac = adapter_mac_addr(padapter);
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- if (da) {
- /* unicast probe request frame */
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
- } else {
- /* broadcast probe request frame */
- _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
- }
- _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- if ((pwdev_priv->pno_mac_addr[0] != 0xFF)
- && (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE)
- && (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) {
- #ifdef CONFIG_RTW_DEBUG
- RTW_DBG("%s pno_scan_seq_num: %d\n", __func__,
- pwdev_priv->pno_scan_seq_num);
- #endif
- SetSeqNum(pwlanhdr, pwdev_priv->pno_scan_seq_num);
- pattrib->seqnum = pwdev_priv->pno_scan_seq_num;
- pattrib->qos_en = 1;
- pwdev_priv->pno_scan_seq_num++;
- } else
- #endif
- {
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- }
- set_frame_sub_type(pframe, WIFI_PROBEREQ);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- if (pssid && !MLME_IS_MESH(padapter))
- pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
- else
- pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
- get_rate_set(padapter, bssrate, &bssrate_len);
- if (bssrate_len > 8) {
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
- pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
- } else
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
- if (ch)
- pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);
- #ifdef CONFIG_RTW_MESH
- if (MLME_IS_MESH(padapter)) {
- if (pssid)
- pframe = rtw_set_ie_mesh_id(pframe, &pattrib->pktlen, pssid->Ssid, pssid->SsidLength);
- else
- pframe = rtw_set_ie_mesh_id(pframe, &pattrib->pktlen, NULL, 0);
- }
- #endif
- if (append_wps) {
- /* add wps_ie for wps2.0 */
- if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
- _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
- pframe += pmlmepriv->wps_probe_req_ie_len;
- pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
- /* pmlmepriv->wps_probe_req_ie_len = 0 ; */ /* reset to zero */
- }
- }
- #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
- pattrib->pktlen += rtw_build_vendor_ie(padapter , pframe , WIFI_PROBEREQ_VENDOR_IE_BIT);
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- if (wait_ack)
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
- exit:
- return ret;
- }
- inline void issue_probereq(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da)
- {
- _issue_probereq(padapter, pssid, da, 0, 1, _FALSE);
- }
- /*
- * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- * try_cnt means the maximal TX count to try
- */
- int issue_probereq_ex(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da, u8 ch, bool append_wps,
- int try_cnt, int wait_ms)
- {
- int ret = _FAIL;
- int i = 0;
- systime start = rtw_get_current_time();
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- do {
- ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms > 0 ? _TRUE : _FALSE);
- i++;
- if (RTW_CANNOT_RUN(padapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- goto exit;
- #endif
- }
- if (try_cnt && wait_ms) {
- if (da)
- RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- else
- RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- /* if psta == NULL, indiate we are station(client) now... */
- void issue_auth(_adapter *padapter, struct sta_info *psta, unsigned short status)
- {
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- unsigned int val32;
- unsigned short val16;
- int use_shared_key = 0;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- return;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_AUTH);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- if (psta) { /* for AP mode */
- #ifdef CONFIG_NATIVEAP_MLME
- _rtw_memcpy(pwlanhdr->addr1, psta->cmn.mac_addr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
- /* setting auth algo number */
- val16 = (u16)psta->authalg;
- if (status != _STATS_SUCCESSFUL_)
- val16 = 0;
- if (val16) {
- val16 = cpu_to_le16(val16);
- use_shared_key = 1;
- }
- pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
- /* setting auth seq number */
- val16 = (u16)psta->auth_seq;
- val16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
- /* setting status code... */
- val16 = status;
- val16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
- /* added challenging text... */
- if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
- pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
- #endif
- } else {
- _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_roam(padapter)) {
- /* 2: 802.11R FTAA */
- val16 = cpu_to_le16(2);
- } else
- #endif
- {
- /* setting auth algo number */
- val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0; /* 0:OPEN System, 1:Shared key */
- if (val16) {
- val16 = cpu_to_le16(val16);
- use_shared_key = 1;
- }
- }
- /* RTW_INFO("%s auth_algo= %s auth_seq=%d\n",__FUNCTION__,(pmlmeinfo->auth_algo==0)?"OPEN":"SHARED",pmlmeinfo->auth_seq); */
- /* setting IV for auth seq #3 */
- if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
- /* RTW_INFO("==> iv(%d),key_index(%d)\n",pmlmeinfo->iv,pmlmeinfo->key_index); */
- val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
- val32 = cpu_to_le32(val32);
- pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&val32, &(pattrib->pktlen));
- pattrib->iv_len = 4;
- }
- pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
- /* setting auth seq number */
- val16 = pmlmeinfo->auth_seq;
- val16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
- /* setting status code... */
- val16 = status;
- val16 = cpu_to_le16(val16);
- pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
- #ifdef CONFIG_RTW_80211R
- rtw_ft_build_auth_req_ies(padapter, pattrib, &pframe);
- #endif
- /* then checking to see if sending challenging text... */
- if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
- pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
- SetPrivacy(fctrl);
- pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->encrypt = _WEP40_;
- pattrib->icv_len = 4;
- pattrib->pktlen += pattrib->icv_len;
- }
- }
- pattrib->last_txcmdsz = pattrib->pktlen;
- rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
- RTW_INFO("%s\n", __FUNCTION__);
- dump_mgntframe(padapter, pmgntframe);
- return;
- }
- void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
- {
- #ifdef CONFIG_AP_MODE
- struct xmit_frame *pmgntframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- struct pkt_attrib *pattrib;
- unsigned char *pbuf, *pframe;
- unsigned short val, ie_status;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
- u8 *ie = pnetwork->IEs;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- #endif /* CONFIG_P2P */
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- return;
- RTW_INFO("%s\n", __FUNCTION__);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->cmn.mac_addr, ETH_ALEN);
- _rtw_memcpy((void *)get_addr2_ptr(pwlanhdr), adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
- set_frame_sub_type(pwlanhdr, pkt_type);
- else
- return;
- pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen += pattrib->hdrlen;
- pframe += pattrib->hdrlen;
- /* capability */
- val = *(unsigned short *)rtw_get_capability_from_ie(ie);
- pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
- ie_status = cpu_to_le16(status);
- pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&ie_status, &(pattrib->pktlen));
- val = cpu_to_le16(pstat->cmn.aid | BIT(14) | BIT(15));
- pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&val, &(pattrib->pktlen));
- if (pstat->bssratelen <= 8)
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
- else {
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
- pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen - 8), pstat->bssrateset + 8, &(pattrib->pktlen));
- }
- #ifdef CONFIG_IEEE80211W
- if (status == _STATS_REFUSED_TEMPORARILY_) {
- u8 timeout_itvl[5];
- u32 timeout_interval = 3000;
- /* Association Comeback time */
- timeout_itvl[0] = 0x03;
- timeout_interval = cpu_to_le32(timeout_interval);
- _rtw_memcpy(timeout_itvl + 1, &timeout_interval, 4);
- pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
- }
- #endif /* CONFIG_IEEE80211W */
- #ifdef CONFIG_80211N_HT
- if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
- uint ie_len = 0;
- /* FILL HT CAP INFO IE */
- /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
- if (pbuf && ie_len > 0) {
- _rtw_memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- }
- /* FILL HT ADD INFO IE */
- /* p = hostapd_eid_ht_operation(hapd, p); */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
- if (pbuf && ie_len > 0) {
- _rtw_memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- }
- }
- #endif
- /*adding EXT_CAPAB_IE */
- if (pmlmepriv->ext_capab_ie_len > 0) {
- uint ie_len = 0;
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
- if (pbuf && ie_len > 0) {
- _rtw_memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- }
- }
- #ifdef CONFIG_80211AC_VHT
- if ((pstat->flags & WLAN_STA_VHT) && (pmlmepriv->vhtpriv.vht_option)
- && (pstat->wpa_pairwise_cipher != WPA_CIPHER_TKIP)
- && (pstat->wpa2_pairwise_cipher != WPA_CIPHER_TKIP)) {
- u32 ie_len = 0;
- /* FILL VHT CAP IE */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
- if (pbuf && ie_len > 0) {
- _rtw_memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- }
- /* FILL VHT OPERATION IE */
- pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTOperation, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
- if (pbuf && ie_len > 0) {
- _rtw_memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- }
- }
- #endif /* CONFIG_80211AC_VHT */
- /* FILL WMM IE */
- if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
- uint ie_len = 0;
- unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
- for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
- pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
- if (pbuf && _rtw_memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
- _rtw_memcpy(pframe, pbuf, ie_len + 2);
- pframe += (ie_len + 2);
- pattrib->pktlen += (ie_len + 2);
- break;
- }
- if ((pbuf == NULL) || (ie_len == 0))
- break;
- }
- }
- if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
- /* add WPS IE ie for wps 2.0 */
- if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
- _rtw_memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
- pframe += pmlmepriv->wps_assoc_resp_ie_len;
- pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
- }
- #ifdef CONFIG_P2P
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE)) {
- u32 len;
- if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
- len = 0;
- if (pmlmepriv->p2p_assoc_resp_ie && pmlmepriv->p2p_assoc_resp_ie_len > 0) {
- len = pmlmepriv->p2p_assoc_resp_ie_len;
- _rtw_memcpy(pframe, pmlmepriv->p2p_assoc_resp_ie, len);
- }
- } else
- len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
- pframe += len;
- pattrib->pktlen += len;
- }
- #ifdef CONFIG_WFD
- if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
- wfdielen = rtw_append_assoc_resp_wfd_ie(padapter, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- }
- #endif
- #endif /* CONFIG_P2P */
- #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
- pattrib->pktlen += rtw_build_vendor_ie(padapter , pframe , WIFI_ASSOCRESP_VENDOR_IE_BIT);
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- #endif
- }
- void _issue_assocreq(_adapter *padapter, u8 is_reassoc)
- {
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- unsigned short val16;
- unsigned int i, j, index = 0;
- unsigned char bssrate[NumRates], sta_bssrate[NumRates];
- PNDIS_802_11_VARIABLE_IEs pIE;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- int bssrate_len = 0, sta_bssrate_len = 0;
- u8 vs_ie_length = 0;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- u8 p2pie[255] = { 0x00 };
- u16 p2pielen = 0;
- #ifdef CONFIG_WFD
- u32 wfdielen = 0;
- #endif
- #endif /* CONFIG_P2P */
- #ifdef CONFIG_DFS
- struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
- u16 cap;
- /* Dot H */
- u8 pow_cap_ele[2] = { 0x00 };
- u8 sup_ch[30 * 2] = {0x00 }, sup_ch_idx = 0, idx_5g = 2; /* For supported channel */
- #endif /* CONFIG_DFS */
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- goto exit;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- if (is_reassoc == _TRUE)
- set_frame_sub_type(pframe, WIFI_REASSOCREQ);
- else
- set_frame_sub_type(pframe, WIFI_ASSOCREQ);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- /* caps */
- #ifdef CONFIG_DFS
- _rtw_memcpy(&cap, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
- cap |= cap_SpecMgmt;
- _rtw_memcpy(pframe, &cap, 2);
- #else
- _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
- #endif /* CONFIG_DFS */
- pframe += 2;
- pattrib->pktlen += 2;
- /* listen interval */
- /* todo: listen interval for power saving */
- val16 = cpu_to_le16(3);
- _rtw_memcpy(pframe , (unsigned char *)&val16, 2);
- pframe += 2;
- pattrib->pktlen += 2;
- /*Construct Current AP Field for Reassoc-Req only*/
- if (is_reassoc == _TRUE) {
- _rtw_memcpy(pframe, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- pframe += ETH_ALEN;
- pattrib->pktlen += ETH_ALEN;
- }
- /* SSID */
- pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
- #ifdef CONFIG_DFS
- /* Dot H */
- if (pmlmeext->cur_channel > 14) {
- pow_cap_ele[0] = 13; /* Minimum transmit power capability */
- pow_cap_ele[1] = 21; /* Maximum transmit power capability */
- pframe = rtw_set_ie(pframe, EID_PowerCap, 2, pow_cap_ele, &(pattrib->pktlen));
- /* supported channels */
- while (sup_ch_idx < rfctl->max_chan_nums && rfctl->channel_set[sup_ch_idx].ChannelNum != 0) {
- if (rfctl->channel_set[sup_ch_idx].ChannelNum <= 14) {
- /* TODO: fix 2.4G supported channel when channel doesn't start from 1 and continuous */
- sup_ch[0] = 1; /* First channel number */
- sup_ch[1] = rfctl->channel_set[sup_ch_idx].ChannelNum; /* Number of channel */
- } else {
- sup_ch[idx_5g++] = rfctl->channel_set[sup_ch_idx].ChannelNum;
- sup_ch[idx_5g++] = 1;
- }
- sup_ch_idx++;
- }
- pframe = rtw_set_ie(pframe, EID_SupportedChannels, idx_5g, sup_ch, &(pattrib->pktlen));
- }
- #endif /* CONFIG_DFS */
- /* supported rate & extended supported rate */
- #if 1 /* Check if the AP's supported rates are also supported by STA. */
- get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
- /* RTW_INFO("sta_bssrate_len=%d\n", sta_bssrate_len); */
- if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */
- sta_bssrate_len = 4;
- /* for (i = 0; i < sta_bssrate_len; i++) { */
- /* RTW_INFO("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
- /* } */
- for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
- if (pmlmeinfo->network.SupportedRates[i] == 0)
- break;
- RTW_INFO("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
- }
- for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
- if (pmlmeinfo->network.SupportedRates[i] == 0)
- break;
- /* Check if the AP's supported rates are also supported by STA. */
- for (j = 0; j < sta_bssrate_len; j++) {
- /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
- if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
- == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
- /* RTW_INFO("match i = %d, j=%d\n", i, j); */
- break;
- } else {
- /* RTW_INFO("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */
- }
- }
- if (j == sta_bssrate_len) {
- /* the rate is not supported by STA */
- RTW_INFO("%s(): the rate[%d]=%02X is not supported by STA!\n", __FUNCTION__, i, pmlmeinfo->network.SupportedRates[i]);
- } else {
- /* the rate is supported by STA */
- bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
- }
- }
- bssrate_len = index;
- RTW_INFO("bssrate_len = %d\n", bssrate_len);
- #else /* Check if the AP's supported rates are also supported by STA. */
- #if 0
- get_rate_set(padapter, bssrate, &bssrate_len);
- #else
- for (bssrate_len = 0; bssrate_len < NumRates; bssrate_len++) {
- if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0)
- break;
- if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0x2C) /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
- break;
- bssrate[bssrate_len] = pmlmeinfo->network.SupportedRates[bssrate_len];
- }
- #endif
- #endif /* Check if the AP's supported rates are also supported by STA. */
- if ((bssrate_len == 0) && (pmlmeinfo->network.SupportedRates[0] != 0)) {
- rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
- rtw_free_xmitframe(pxmitpriv, pmgntframe);
- goto exit; /* don't connect to AP if no joint supported rate */
- }
- if (bssrate_len > 8) {
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
- pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
- } else if (bssrate_len > 0)
- pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
- else
- RTW_INFO("%s: Connect to AP without 11b and 11g data rate!\n", __FUNCTION__);
- #ifdef CONFIG_RTW_80211K
- if (pmlmeinfo->network.PhyInfo.rm_en_cap[0] /* RM Enabled Capabilities */
- | pmlmeinfo->network.PhyInfo.rm_en_cap[1]
- | pmlmeinfo->network.PhyInfo.rm_en_cap[2]
- | pmlmeinfo->network.PhyInfo.rm_en_cap[3]
- | pmlmeinfo->network.PhyInfo.rm_en_cap[4])
- pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_, 5,
- (u8 *)padapter->rmpriv.rm_en_cap_def, &(pattrib->pktlen));
- #endif /* CONFIG_RTW_80211K */
- /* vendor specific IE, such as WPA, WMM, WPS */
- for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;) {
- pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
- switch (pIE->ElementID) {
- case _VENDOR_SPECIFIC_IE_:
- if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
- (_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||
- (_rtw_memcmp(pIE->data, WPS_OUI, 4))) {
- vs_ie_length = pIE->Length;
- if ((!padapter->registrypriv.wifi_spec) && (_rtw_memcmp(pIE->data, WPS_OUI, 4))) {
- /* Commented by Kurt 20110629 */
- /* In some older APs, WPS handshake */
- /* would be fail if we append vender extensions informations to AP */
- vs_ie_length = 14;
- }
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));
- }
- break;
- case EID_WPA2:
- #ifdef CONFIG_RTW_80211R
- if ((is_reassoc) && (rtw_ft_roam(padapter))) {
- rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe);
- } else
- #endif
- pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));
- break;
- #ifdef CONFIG_80211N_HT
- case EID_HTCapability:
- if (padapter->mlmepriv.htpriv.ht_option == _TRUE) {
- if (!(is_ap_in_tkip(padapter))) {
- _rtw_memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
- pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
- pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
- }
- }
- break;
- case EID_EXTCapability:
- if (padapter->mlmepriv.htpriv.ht_option == _TRUE)
- pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
- break;
- #endif /* CONFIG_80211N_HT */
- #ifdef CONFIG_80211AC_VHT
- case EID_VHTCapability:
- if (padapter->mlmepriv.vhtpriv.vht_option == _TRUE)
- pframe = rtw_set_ie(pframe, EID_VHTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
- break;
- case EID_OpModeNotification:
- if (padapter->mlmepriv.vhtpriv.vht_option == _TRUE)
- pframe = rtw_set_ie(pframe, EID_OpModeNotification, pIE->Length, pIE->data, &(pattrib->pktlen));
- break;
- #endif /* CONFIG_80211AC_VHT */
- default:
- break;
- }
- i += (pIE->Length + 2);
- }
- if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
- #ifdef CONFIG_WAPI_SUPPORT
- rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib);
- #endif
- #ifdef CONFIG_P2P
- #ifdef CONFIG_IOCTL_CFG80211
- if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {
- if (pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len > 0) {
- _rtw_memcpy(pframe, pmlmepriv->p2p_assoc_req_ie, pmlmepriv->p2p_assoc_req_ie_len);
- pframe += pmlmepriv->p2p_assoc_req_ie_len;
- pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
- }
- } else
- #endif /* CONFIG_IOCTL_CFG80211 */
- {
- if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
- /* Should add the P2P IE in the association request frame. */
- /* P2P OUI */
- p2pielen = 0;
- p2pie[p2pielen++] = 0x50;
- p2pie[p2pielen++] = 0x6F;
- p2pie[p2pielen++] = 0x9A;
- p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
- /* Commented by Albert 20101109 */
- /* According to the P2P Specification, the association request frame should contain 3 P2P attributes */
- /* 1. P2P Capability */
- /* 2. Extended Listen Timing */
- /* 3. Device Info */
- /* Commented by Albert 20110516 */
- /* 4. P2P Interface */
- /* P2P Capability */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
- p2pielen += 2;
- /* Value: */
- /* Device Capability Bitmap, 1 byte */
- p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
- /* Group Capability Bitmap, 1 byte */
- if (pwdinfo->persistent_supported)
- p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
- else
- p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
- /* Extended Listen Timing */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
- p2pielen += 2;
- /* Value: */
- /* Availability Period */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
- p2pielen += 2;
- /* Availability Interval */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
- p2pielen += 2;
- /* Device Info */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
- /* Length: */
- /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
- /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- /* P2P Device Address */
- _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
- p2pielen += ETH_ALEN;
- /* Config Method */
- /* This field should be big endian. Noted by P2P specification. */
- if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
- (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
- else
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);
- p2pielen += 2;
- /* Primary Device Type */
- /* Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
- p2pielen += 2;
- /* OUI */
- *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
- p2pielen += 4;
- /* Sub Category ID */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
- p2pielen += 2;
- /* Number of Secondary Device Types */
- p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
- /* Device Name */
- /* Type: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
- p2pielen += 2;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
- p2pielen += 2;
- /* Value: */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
- p2pielen += pwdinfo->device_name_len;
- /* P2P Interface */
- /* Type: */
- p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
- /* Length: */
- *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);
- p2pielen += 2;
- /* Value: */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Device Address */
- p2pielen += ETH_ALEN;
- p2pie[p2pielen++] = 1; /* P2P Interface Address Count */
- _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Interface Address List */
- p2pielen += ETH_ALEN;
- pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
- }
- }
- #endif /* CONFIG_P2P */
- #ifdef CONFIG_WFD
- wfdielen = rtw_append_assoc_req_wfd_ie(padapter, pframe);
- pframe += wfdielen;
- pattrib->pktlen += wfdielen;
- #endif
- #ifdef CONFIG_RTW_REPEATER_SON
- rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen);
- #endif
- #ifdef CONFIG_APPEND_VENDOR_IE_ENABLE
- pattrib->pktlen += rtw_build_vendor_ie(padapter , pframe , WIFI_ASSOCREQ_VENDOR_IE_BIT);
- #endif
- #ifdef CONFIG_RTW_80211R
- rtw_ft_build_assoc_req_ies(padapter, is_reassoc, pattrib, &pframe);
- #endif
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- exit:
- if (ret == _SUCCESS)
- rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
- else
- rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
- return;
- }
- void issue_assocreq(_adapter *padapter)
- {
- _issue_assocreq(padapter, _FALSE);
- }
- void issue_reassocreq(_adapter *padapter)
- {
- _issue_assocreq(padapter, _TRUE);
- }
- /* when wait_ack is ture, this function shoule be called at process context */
- static int _issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
- {
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv;
- struct mlme_ext_priv *pmlmeext;
- struct mlme_ext_info *pmlmeinfo;
- u8 a4_shift;
- /* RTW_INFO("%s:%d\n", __FUNCTION__, power_mode); */
- if (!padapter)
- goto exit;
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- pxmitpriv = &(padapter->xmitpriv);
- pmlmeext = &(padapter->mlmeextpriv);
- pmlmeinfo = &(pmlmeext->mlmext_info);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- goto exit;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->retry_ctrl = _FALSE;
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- if (MLME_IS_AP(padapter))
- SetFrDs(fctrl);
- else if (MLME_IS_STA(padapter))
- SetToDs(fctrl);
- else if (MLME_IS_MESH(padapter)) {
- SetToDs(fctrl);
- SetFrDs(fctrl);
- }
- if (power_mode)
- SetPwrMgt(fctrl);
- if (get_tofr_ds(fctrl) == 3) {
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr4, adapter_mac_addr(padapter), ETH_ALEN);
- a4_shift = ETH_ALEN;
- pattrib->hdrlen += ETH_ALEN;
- } else {
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- a4_shift = 0;
- }
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_DATA_NULL);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr) + a4_shift;
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr) + a4_shift;
- pattrib->last_txcmdsz = pattrib->pktlen;
- if (wait_ack)
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
- exit:
- return ret;
- }
- /*
- * When wait_ms > 0, this function should be called at process context
- * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- * try_cnt means the maximal TX count to try
- * da == NULL for station mode
- */
- int issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
- {
- int ret = _FAIL;
- int i = 0;
- systime start = rtw_get_current_time();
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- /* da == NULL, assum it's null data for sta to ap */
- if (da == NULL)
- da = get_my_bssid(&(pmlmeinfo->network));
- do {
- ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? _TRUE : _FALSE);
- i++;
- if (RTW_CANNOT_RUN(padapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- goto exit;
- #endif
- }
- if (try_cnt && wait_ms) {
- if (da)
- RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- else
- RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- /* when wait_ack is ture, this function shoule be called at process context */
- static int _issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, u8 ps, int wait_ack)
- {
- int ret = _FAIL;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl, *qc;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 a4_shift;
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- /* RTW_INFO("%s\n", __FUNCTION__); */
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- goto exit;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->hdrlen += 2;
- pattrib->qos_en = _TRUE;
- pattrib->eosp = 1;
- pattrib->ack_policy = 0;
- pattrib->mdata = 0;
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- if (MLME_IS_AP(padapter))
- SetFrDs(fctrl);
- else if (MLME_IS_STA(padapter))
- SetToDs(fctrl);
- else if (MLME_IS_MESH(padapter)) {
- SetToDs(fctrl);
- SetFrDs(fctrl);
- }
- if (ps)
- SetPwrMgt(fctrl);
- if (pattrib->mdata)
- SetMData(fctrl);
- if (get_tofr_ds(fctrl) == 3) {
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr4, adapter_mac_addr(padapter), ETH_ALEN);
- a4_shift = ETH_ALEN;
- pattrib->hdrlen += ETH_ALEN;
- } else {
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- a4_shift = 0;
- }
- qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
- SetPriority(qc, tid);
- SetEOSP(qc, pattrib->eosp);
- SetAckpolicy(qc, pattrib->ack_policy);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos) + a4_shift;
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos) + a4_shift;
- pattrib->last_txcmdsz = pattrib->pktlen;
- if (wait_ack)
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
- exit:
- return ret;
- }
- /*
- * when wait_ms >0 , this function should be called at process context
- * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- * try_cnt means the maximal TX count to try
- * da == NULL for station mode
- */
- int issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, u8 ps, int try_cnt, int wait_ms)
- {
- int ret = _FAIL;
- int i = 0;
- systime start = rtw_get_current_time();
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- /* da == NULL, assum it's null data for sta to ap*/
- if (da == NULL)
- da = get_my_bssid(&(pmlmeinfo->network));
- do {
- ret = _issue_qos_nulldata(padapter, da, tid, ps, wait_ms > 0 ? _TRUE : _FALSE);
- i++;
- if (RTW_CANNOT_RUN(padapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- goto exit;
- #endif
- }
- if (try_cnt && wait_ms) {
- if (da)
- RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- else
- RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- static int _issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack, u8 key_type)
- {
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- int ret = _FAIL;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #endif /* CONFIG_P2P */
- /* RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
- #ifdef CONFIG_P2P
- if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
- _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
- _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
- }
- #endif /* CONFIG_P2P */
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- goto exit;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->retry_ctrl = _FALSE;
- pattrib->key_type = key_type;
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_DEAUTH);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- reason = cpu_to_le16(reason);
- pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&reason, &(pattrib->pktlen));
- pattrib->last_txcmdsz = pattrib->pktlen;
- if (wait_ack)
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
- exit:
- return ret;
- }
- int issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason)
- {
- RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
- return _issue_deauth(padapter, da, reason, _FALSE, IEEE80211W_RIGHT_KEY);
- }
- #ifdef CONFIG_IEEE80211W
- int issue_deauth_11w(_adapter *padapter, unsigned char *da, unsigned short reason, u8 key_type)
- {
- RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
- return _issue_deauth(padapter, da, reason, _FALSE, key_type);
- }
- #endif /* CONFIG_IEEE80211W */
- /*
- * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- * try_cnt means the maximal TX count to try
- */
- int issue_deauth_ex(_adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
- int wait_ms)
- {
- int ret = _FAIL;
- int i = 0;
- systime start = rtw_get_current_time();
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- do {
- ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? _TRUE : _FALSE, IEEE80211W_RIGHT_KEY);
- i++;
- if (RTW_CANNOT_RUN(padapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- goto exit;
- #endif
- }
- if (try_cnt && wait_ms) {
- if (da)
- RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- else
- RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
- {
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- return;
- RTW_INFO(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n",
- FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */
- _rtw_memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- /* category, action */
- {
- u8 category, action;
- category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
- action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- }
- pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);
- pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
- hal_ch_offset_to_secondary_ch_offset(ch_offset));
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- }
- #ifdef CONFIG_IEEE80211W
- void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid, u8 key_type)
- {
- u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
- u16 reason_code;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- u8 *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- u16 *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct registry_priv *pregpriv = &padapter->registrypriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- return;
- RTW_INFO("%s, %04x\n", __FUNCTION__, tid);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL) {
- RTW_INFO("%s: alloc_mgtxmitframe fail\n", __FUNCTION__);
- return;
- }
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- pattrib->key_type = key_type;
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- if (raddr)
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
- else
- _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
- pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
- switch (action) {
- case 0: /* SA Query req */
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
- pmlmeext->sa_query_seq++;
- /* send sa query request to AP, AP should reply sa query response in 1 second */
- if (pattrib->key_type == IEEE80211W_RIGHT_KEY) {
- psta = rtw_get_stainfo(pstapriv, pwlanhdr->addr1);
- if (psta != NULL) {
- /* RTW_INFO("%s, %d, set dot11w_expire_timer\n", __func__, __LINE__); */
- _set_timer(&psta->dot11w_expire_timer, 1000);
- }
- }
- break;
- case 1: /* SA Query rsp */
- tid = cpu_to_le16(tid);
- /* RTW_INFO("rtw_set_fixed_ie, %04x\n", tid); */
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&tid, &pattrib->pktlen);
- break;
- default:
- break;
- }
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- }
- #endif /* CONFIG_IEEE80211W */
- /**
- * issue_action_ba - internal function to TX Block Ack action frame
- * @padapter: the adapter to TX
- * @raddr: receiver address
- * @action: Block Ack Action
- * @tid: tid
- * @size: the announced AMPDU buffer size. used by ADDBA_RESP
- * @status: status/reason code. used by ADDBA_RESP, DELBA
- * @initiator: if we are the initiator of AMPDU association. used by DELBA
- * @wait_ack: used xmit ack
- *
- * Returns:
- * _SUCCESS: No xmit ack is used or acked
- * _FAIL: not acked when using xmit ack
- */
- static int issue_action_ba(_adapter *padapter, unsigned char *raddr, unsigned char action
- , u8 tid, u8 size, u16 status, u8 initiator, int wait_ack)
- {
- int ret = _FAIL;
- u8 category = RTW_WLAN_CATEGORY_BACK;
- u16 start_seq;
- u16 BA_para_set;
- u16 BA_timeout_value;
- u16 BA_starting_seqctrl;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- u8 *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- u16 *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct sta_info *psta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct registry_priv *pregpriv = &padapter->registrypriv;
- #ifdef CONFIG_80211N_HT
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- goto exit;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- /* _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- if (category == 3) {
- switch (action) {
- case RTW_WLAN_ACTION_ADDBA_REQ:
- do {
- pmlmeinfo->dialogToken++;
- } while (pmlmeinfo->dialogToken == 0);
- pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
- #if defined(CONFIG_RTL8188E) && defined(CONFIG_SDIO_HCI)
- BA_para_set = (0x0802 | ((tid & 0xf) << 2)); /* immediate ack & 16 buffer size */
- #else
- BA_para_set = (0x1002 | ((tid & 0xf) << 2)); /* immediate ack & 64 buffer size */
- #endif
- #ifdef CONFIG_TX_AMSDU
- if (padapter->tx_amsdu >= 1) /* TX AMSDU enabled */
- BA_para_set |= BIT(0);
- else /* TX AMSDU disabled */
- BA_para_set &= ~BIT(0);
- #endif
- BA_para_set = cpu_to_le16(BA_para_set);
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
- /* BA_timeout_value = 0xffff; */ /* max: 65535 TUs(~ 65 ms) */
- BA_timeout_value = 5000;/* ~ 5ms */
- BA_timeout_value = cpu_to_le16(BA_timeout_value);
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_timeout_value)), &(pattrib->pktlen));
- /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */
- psta = rtw_get_stainfo(pstapriv, raddr);
- if (psta != NULL) {
- start_seq = (psta->sta_xmitpriv.txseq_tid[tid & 0x07] & 0xfff) + 1;
- RTW_INFO("BA_starting_seqctrl = %d for TID=%d\n", start_seq, tid & 0x07);
- psta->BA_starting_seqctrl[tid & 0x07] = start_seq;
- BA_starting_seqctrl = start_seq << 4;
- }
- BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_starting_seqctrl)), &(pattrib->pktlen));
- break;
- case RTW_WLAN_ACTION_ADDBA_RESP:
- pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
- status = cpu_to_le16(status);
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
- BA_para_set = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set);
- BA_para_set &= ~IEEE80211_ADDBA_PARAM_TID_MASK;
- BA_para_set |= (tid << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
- BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
- BA_para_set |= (size << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
- if (!padapter->registrypriv.wifi_spec) {
- if (pregpriv->rx_ampdu_amsdu == 0) /* disabled */
- BA_para_set &= ~BIT(0);
- else if (pregpriv->rx_ampdu_amsdu == 1) /* enabled */
- BA_para_set |= BIT(0);
- }
- BA_para_set = cpu_to_le16(BA_para_set);
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
- break;
- case RTW_WLAN_ACTION_DELBA:
- BA_para_set = 0;
- BA_para_set |= (tid << 12) & IEEE80211_DELBA_PARAM_TID_MASK;
- BA_para_set |= (initiator << 11) & IEEE80211_DELBA_PARAM_INITIATOR_MASK;
- BA_para_set = cpu_to_le16(BA_para_set);
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
- status = cpu_to_le16(status);
- pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(status)), &(pattrib->pktlen));
- break;
- default:
- break;
- }
- }
- pattrib->last_txcmdsz = pattrib->pktlen;
- if (wait_ack)
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
- exit:
- #endif /* CONFIG_80211N_HT */
- return ret;
- }
- /**
- * issue_addba_req - TX ADDBA_REQ
- * @adapter: the adapter to TX
- * @ra: receiver address
- * @tid: tid
- */
- inline void issue_addba_req(_adapter *adapter, unsigned char *ra, u8 tid)
- {
- issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_REQ
- , tid
- , 0 /* unused */
- , 0 /* unused */
- , 0 /* unused */
- , _FALSE
- );
- RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" tid=%u\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), tid);
- }
- /**
- * issue_addba_rsp - TX ADDBA_RESP
- * @adapter: the adapter to TX
- * @ra: receiver address
- * @tid: tid
- * @status: status code
- * @size: the announced AMPDU buffer size
- */
- inline void issue_addba_rsp(_adapter *adapter, unsigned char *ra, u8 tid, u16 status, u8 size)
- {
- issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_RESP
- , tid
- , size
- , status
- , 0 /* unused */
- , _FALSE
- );
- RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" status=%u, tid=%u, size=%u\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), status, tid, size);
- }
- /**
- * issue_addba_rsp_wait_ack - TX ADDBA_RESP and wait ack
- * @adapter: the adapter to TX
- * @ra: receiver address
- * @tid: tid
- * @status: status code
- * @size: the announced AMPDU buffer size
- * @try_cnt: the maximal TX count to try
- * @wait_ms: == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- */
- inline u8 issue_addba_rsp_wait_ack(_adapter *adapter, unsigned char *ra, u8 tid, u16 status, u8 size, int try_cnt, int wait_ms)
- {
- int ret = _FAIL;
- int i = 0;
- systime start = rtw_get_current_time();
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(adapter)))
- goto exit;
- do {
- ret = issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_RESP
- , tid
- , size
- , status
- , 0 /* unused */
- , _TRUE
- );
- i++;
- if (RTW_CANNOT_RUN(adapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- /* goto exit; */
- #endif
- }
- if (try_cnt && wait_ms) {
- RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" status:=%u tid=%u size:%u%s, %d/%d in %u ms\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), status, tid, size
- , ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- /**
- * issue_del_ba - TX DELBA
- * @adapter: the adapter to TX
- * @ra: receiver address
- * @tid: tid
- * @reason: reason code
- * @initiator: if we are the initiator of AMPDU association. used by DELBA
- */
- inline void issue_del_ba(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator)
- {
- issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA
- , tid
- , 0 /* unused */
- , reason
- , initiator
- , _FALSE
- );
- RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator);
- }
- /**
- * issue_del_ba_ex - TX DELBA with xmit ack options
- * @adapter: the adapter to TX
- * @ra: receiver address
- * @tid: tid
- * @reason: reason code
- * @initiator: if we are the initiator of AMPDU association. used by DELBA
- * @try_cnt: the maximal TX count to try
- * @wait_ms: == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- */
- int issue_del_ba_ex(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator
- , int try_cnt, int wait_ms)
- {
- int ret = _FAIL;
- int i = 0;
- systime start = rtw_get_current_time();
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(adapter)))
- goto exit;
- do {
- ret = issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA
- , tid
- , 0 /* unused */
- , reason
- , initiator
- , wait_ms > 0 ? _TRUE : _FALSE
- );
- i++;
- if (RTW_CANNOT_RUN(adapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- /* goto exit; */
- #endif
- }
- if (try_cnt && wait_ms) {
- RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u%s, %d/%d in %u ms\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator
- , ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- void issue_action_BSSCoexistPacket(_adapter *padapter)
- {
- _irqL irqL;
- _list *plist, *phead;
- unsigned char category, action;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct wlan_network *pnetwork = NULL;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- _queue *queue = &(pmlmepriv->scanned_queue);
- u8 InfoContent[16] = {0};
- u8 ICS[8][15];
- #ifdef CONFIG_80211N_HT
- if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
- return;
- if (_TRUE == pmlmeinfo->bwmode_updated)
- return;
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- return;
- RTW_INFO("%s\n", __FUNCTION__);
- category = RTW_WLAN_CATEGORY_PUBLIC;
- action = ACT_PUBLIC_BSSCOEXIST;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- /* */
- if (pmlmepriv->num_FortyMHzIntolerant > 0) {
- u8 iedata = 0;
- iedata |= BIT(2);/* 20 MHz BSS Width Request */
- pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
- }
- /* */
- _rtw_memset(ICS, 0, sizeof(ICS));
- if (pmlmepriv->num_sta_no_ht > 0) {
- int i;
- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
- phead = get_list_head(queue);
- plist = get_next(phead);
- while (1) {
- int len;
- u8 *p;
- WLAN_BSSID_EX *pbss_network;
- if (rtw_end_of_queue_search(phead, plist) == _TRUE)
- break;
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
- plist = get_next(plist);
- pbss_network = (WLAN_BSSID_EX *)&pnetwork->network;
- p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
- if ((p == NULL) || (len == 0)) { /* non-HT */
- if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
- continue;
- ICS[0][pbss_network->Configuration.DSConfig] = 1;
- if (ICS[0][0] == 0)
- ICS[0][0] = 1;
- }
- }
- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
- for (i = 0; i < 8; i++) {
- if (ICS[i][0] == 1) {
- int j, k = 0;
- InfoContent[k] = i;
- /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i); */
- k++;
- for (j = 1; j <= 14; j++) {
- if (ICS[i][j] == 1) {
- if (k < 16) {
- InfoContent[k] = j; /* channel number */
- /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
- k++;
- }
- }
- }
- pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
- }
- }
- }
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- #endif /* CONFIG_80211N_HT */
- }
- /* Spatial Multiplexing Powersave (SMPS) action frame */
- int _issue_action_SM_PS(_adapter *padapter , unsigned char *raddr , u8 NewMimoPsMode , u8 wait_ack)
- {
- int ret = _FAIL;
- unsigned char category = RTW_WLAN_CATEGORY_HT;
- u8 action = RTW_WLAN_ACTION_HT_SM_PS;
- u8 sm_power_control = 0;
- struct xmit_frame *pmgntframe;
- struct pkt_attrib *pattrib;
- unsigned char *pframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- unsigned short *fctrl;
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_DISABLED) {
- sm_power_control = sm_power_control & ~(BIT(0)); /* SM Power Save Enable = 0 SM Power Save Disable */
- } else if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_STATIC) {
- sm_power_control = sm_power_control | BIT(0); /* SM Power Save Enable = 1 SM Power Save Enable */
- sm_power_control = sm_power_control & ~(BIT(1)); /* SM Mode = 0 Static Mode */
- } else if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_DYNAMIC) {
- sm_power_control = sm_power_control | BIT(0); /* SM Power Save Enable = 1 SM Power Save Enable */
- sm_power_control = sm_power_control | BIT(1); /* SM Mode = 1 Dynamic Mode */
- } else
- return ret;
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- return ret;
- RTW_INFO("%s, sm_power_control=%u, NewMimoPsMode=%u\n", __FUNCTION__ , sm_power_control , NewMimoPsMode);
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return ret;
- /* update attribute */
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- fctrl = &(pwlanhdr->frame_ctl);
- *(fctrl) = 0;
- _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); /* RA */
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); /* DA = RA */
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- /* category, action */
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(sm_power_control), &(pattrib->pktlen));
- pattrib->last_txcmdsz = pattrib->pktlen;
- if (wait_ack)
- ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
- else {
- dump_mgntframe(padapter, pmgntframe);
- ret = _SUCCESS;
- }
- if (ret != _SUCCESS)
- RTW_INFO("%s, ack to\n", __func__);
- return ret;
- }
- /*
- * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
- * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
- * try_cnt means the maximal TX count to try
- */
- int issue_action_SM_PS_wait_ack(_adapter *padapter, unsigned char *raddr, u8 NewMimoPsMode, int try_cnt, int wait_ms)
- {
- int ret = _FAIL;
- int i = 0;
- systime start = rtw_get_current_time();
- if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
- goto exit;
- do {
- ret = _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , wait_ms > 0 ? _TRUE : _FALSE);
- i++;
- if (RTW_CANNOT_RUN(padapter))
- break;
- if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
- rtw_msleep_os(wait_ms);
- } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
- if (ret != _FAIL) {
- ret = _SUCCESS;
- #ifndef DBG_XMIT_ACK
- goto exit;
- #endif
- }
- if (try_cnt && wait_ms) {
- if (raddr)
- RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", %s , %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter), MAC_ARG(raddr),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- else
- RTW_INFO(FUNC_ADPT_FMT", %s , %d/%d in %u ms\n",
- FUNC_ADPT_ARG(padapter),
- ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
- }
- exit:
- return ret;
- }
- int issue_action_SM_PS(_adapter *padapter , unsigned char *raddr , u8 NewMimoPsMode)
- {
- RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(raddr));
- return _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , _FALSE);
- }
- /**
- * _send_delba_sta_tid - Cancel the AMPDU association for the specific @sta, @tid
- * @adapter: the adapter to which @sta belongs
- * @initiator: if we are the initiator of AMPDU association
- * @sta: the sta to be checked
- * @tid: the tid to be checked
- * @force: cancel and send DELBA even when no AMPDU association is setup
- * @wait_ack: send delba with xmit ack (valid when initiator == 0)
- *
- * Returns:
- * _FAIL if sta is NULL
- * when initiator is 1, always _SUCCESS
- * when initiator is 0, _SUCCESS if DELBA is acked
- */
- static unsigned int _send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid
- , u8 force, int wait_ack)
- {
- int ret = _SUCCESS;
- if (sta == NULL) {
- ret = _FAIL;
- goto exit;
- }
- if (initiator == 0) {
- /* recipient */
- if (force || sta->recvreorder_ctrl[tid].enable == _TRUE) {
- u8 ampdu_size_bak = sta->recvreorder_ctrl[tid].ampdu_size;
- sta->recvreorder_ctrl[tid].enable = _FALSE;
- sta->recvreorder_ctrl[tid].ampdu_size = RX_AMPDU_SIZE_INVALID;
- if (rtw_del_rx_ampdu_test_trigger_no_tx_fail())
- ret = _FAIL;
- else if (wait_ack)
- ret = issue_del_ba_ex(adapter, sta->cmn.mac_addr, tid, 37, initiator, 3, 1);
- else
- issue_del_ba(adapter, sta->cmn.mac_addr, tid, 37, initiator);
- if (ret == _FAIL && sta->recvreorder_ctrl[tid].enable == _FALSE)
- sta->recvreorder_ctrl[tid].ampdu_size = ampdu_size_bak;
- }
- } else if (initiator == 1) {
- /* originator */
- #ifdef CONFIG_80211N_HT
- if (force || sta->htpriv.agg_enable_bitmap & BIT(tid)) {
- sta->htpriv.agg_enable_bitmap &= ~BIT(tid);
- sta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
- issue_del_ba(adapter, sta->cmn.mac_addr, tid, 37, initiator);
- }
- #endif
- }
- exit:
- return ret;
- }
- inline unsigned int send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid
- , u8 force)
- {
- return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 0);
- }
- inline unsigned int send_delba_sta_tid_wait_ack(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid
- , u8 force)
- {
- return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 1);
- }
- unsigned int send_delba(_adapter *padapter, u8 initiator, u8 *addr)
- {
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *psta = NULL;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u16 tid;
- if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
- return _SUCCESS;
- psta = rtw_get_stainfo(pstapriv, addr);
- if (psta == NULL)
- return _SUCCESS;
- #if 0
- RTW_INFO("%s:%s\n", __func__, (initiator == 0) ? "RX_DIR" : "TX_DIR");
- if (initiator == 1) /* originator */
- RTW_INFO("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap);
- #endif
- for (tid = 0; tid < TID_NUM; tid++)
- send_delba_sta_tid(padapter, initiator, psta, tid, 0);
- return _SUCCESS;
- }
- unsigned int send_beacon(_adapter *padapter)
- {
- #ifdef CONFIG_PCI_HCI
- #ifdef CONFIG_FW_HANDLE_TXBCN
- u8 vap_id = padapter->vap_id;
- /* bypass TX BCN because vap_id is invalid*/
- if (vap_id == CONFIG_LIMITED_AP_NUM)
- return _SUCCESS;
- #endif
- /* bypass TX BCN queue because op ch is switching/waiting */
- if (check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING)
- || IS_CH_WAITING(adapter_to_rfctl(padapter))
- )
- return _SUCCESS;
- /* RTW_INFO("%s\n", __FUNCTION__); */
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
- /* 8192EE Port select for Beacon DL */
- rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
- #ifdef CONFIG_FW_HANDLE_TXBCN
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);
- #endif
- issue_beacon(padapter, 0);
- #ifdef CONFIG_FW_HANDLE_TXBCN
- vap_id = 0xFF;
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);
- #endif
- #ifdef RTL8814AE_SW_BCN
- if (GET_HAL_DATA(padapter)->bCorrectBCN != 0)
- RTW_INFO("%s, line%d, Warnning, pHalData->bCorrectBCN != 0\n", __func__, __LINE__);
- GET_HAL_DATA(padapter)->bCorrectBCN = 1;
- #endif
- return _SUCCESS;
- #endif /*CONFIG_PCI_HCI*/
- #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
- u8 bxmitok = _FALSE;
- int issue = 0;
- int poll = 0;
- systime start = rtw_get_current_time();
- #ifdef CONFIG_FW_HANDLE_TXBCN
- u8 vap_id = padapter->vap_id;
- /* bypass TX BCN because vap_id is invalid*/
- if (vap_id == CONFIG_LIMITED_AP_NUM)
- return _SUCCESS;
- #endif
- /* bypass TX BCN queue because op ch is switching/waiting */
- if (check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING)
- || IS_CH_WAITING(adapter_to_rfctl(padapter))
- )
- return _SUCCESS;
- #if defined(CONFIG_USB_HCI)
- #if defined(CONFIG_RTL8812A)
- if (IS_FULL_SPEED_USB(padapter)) {
- issue_beacon(padapter, 300);
- bxmitok = _TRUE;
- } else
- #endif
- #endif
- {
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
- rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
- #ifdef CONFIG_FW_HANDLE_TXBCN
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);
- #endif
- do {
- issue_beacon(padapter, 100);
- issue++;
- do {
- rtw_yield_os();
- rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
- poll++;
- } while ((poll % 10) != 0 && _FALSE == bxmitok && !RTW_CANNOT_RUN(padapter));
- } while (bxmitok == _FALSE && (issue < 100) && !RTW_CANNOT_RUN(padapter));
- #ifdef CONFIG_FW_HANDLE_TXBCN
- vap_id = 0xFF;
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);
- #endif
- }
- if (RTW_CANNOT_RUN(padapter))
- return _FAIL;
- if (_FALSE == bxmitok) {
- RTW_INFO("%s fail! %u ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
- #ifdef CONFIG_BCN_RECOVERY
- GET_HAL_DATA(padapter)->issue_bcn_fail++;
- #endif /*CONFIG_BCN_RECOVERY*/
- return _FAIL;
- } else {
- u32 passing_time = rtw_get_passing_time_ms(start);
- if (passing_time > 100 || issue > 3)
- RTW_INFO("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
- else if (0)
- RTW_INFO("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
- #ifdef CONFIG_FW_CORRECT_BCN
- rtw_hal_fw_correct_bcn(padapter);
- #endif
- return _SUCCESS;
- }
- #endif /*defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)*/
- }
- /****************************************************************************
- Following are some utitity fuctions for WiFi MLME
- *****************************************************************************/
- BOOLEAN IsLegal5GChannel(
- IN PADAPTER Adapter,
- IN u8 channel)
- {
- int i = 0;
- u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
- 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
- 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
- 161, 163, 165
- };
- for (i = 0; i < sizeof(Channel_5G); i++)
- if (channel == Channel_5G[i])
- return _TRUE;
- return _FALSE;
- }
- /* collect bss info from Beacon and Probe request/response frames. */
- u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSID_EX *bssid)
- {
- int i;
- sint len;
- u8 *p;
- u8 rf_path;
- u16 val16, subtype;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- u32 packet_len = precv_frame->u.hdr.len;
- u8 ie_offset;
- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
- if (len > MAX_IE_SZ) {
- /* RTW_INFO("IE too long for survey event\n"); */
- return _FAIL;
- }
- _rtw_memset(bssid, 0, sizeof(WLAN_BSSID_EX));
- subtype = get_frame_sub_type(pframe);
- if (subtype == WIFI_BEACON) {
- bssid->Reserved[0] = BSS_TYPE_BCN;
- ie_offset = _BEACON_IE_OFFSET_;
- } else {
- /* FIXME : more type */
- if (subtype == WIFI_PROBERSP) {
- ie_offset = _PROBERSP_IE_OFFSET_;
- bssid->Reserved[0] = BSS_TYPE_PROB_RSP;
- } else if (subtype == WIFI_PROBEREQ) {
- ie_offset = _PROBEREQ_IE_OFFSET_;
- bssid->Reserved[0] = BSS_TYPE_PROB_REQ;
- } else {
- bssid->Reserved[0] = BSS_TYPE_UNDEF;
- ie_offset = _FIXED_IE_LENGTH_;
- }
- }
- bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len;
- /* below is to copy the information element */
- bssid->IELength = len;
- _rtw_memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
- /* get the signal strength */
- /* bssid->Rssi = precv_frame->u.hdr.attrib.SignalStrength; */ /* 0-100 index. */
- bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.recv_signal_power; /* in dBM.raw data */
- bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.signal_quality;/* in percentage */
- bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.signal_strength;/* in percentage */
- /* get rx_snr */
- if (precv_frame->u.hdr.attrib.data_rate >= DESC_RATE11M) {
- bssid->PhyInfo.is_cck_rate = 0;
- for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++)
- bssid->PhyInfo.rx_snr[rf_path] =
- precv_frame->u.hdr.attrib.phy_info.rx_snr[rf_path];
- } else
- bssid->PhyInfo.is_cck_rate = 1;
- #ifdef CONFIG_ANTENNA_DIVERSITY
- rtw_hal_get_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &(bssid->PhyInfo.Optimum_antenna), NULL);
- #endif
- /* checking SSID */
- p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
- if (p == NULL) {
- RTW_INFO("marc: cannot find SSID for survey event\n");
- return _FAIL;
- }
- if (*(p + 1)) {
- if (len > NDIS_802_11_LENGTH_SSID) {
- RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
- return _FAIL;
- }
- _rtw_memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
- bssid->Ssid.SsidLength = *(p + 1);
- } else
- bssid->Ssid.SsidLength = 0;
- _rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
- /* checking rate info... */
- i = 0;
- p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
- if (p != NULL) {
- if (len > NDIS_802_11_LENGTH_RATES_EX) {
- RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
- return _FAIL;
- }
- if (rtw_validate_value(_SUPPORTEDRATES_IE_, p+2, len) == _FALSE) {
- rtw_absorb_ssid_ifneed(padapter, bssid, pframe);
- RTW_DBG_DUMP("Invalidated Support Rate IE --", p, len+2);
- return _FAIL;
- }
- _rtw_memcpy(bssid->SupportedRates, (p + 2), len);
- i = len;
- }
- p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
- if (p != NULL) {
- if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) {
- RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
- return _FAIL;
- }
- if (rtw_validate_value(_EXT_SUPPORTEDRATES_IE_, p+2, len) == _FALSE) {
- rtw_absorb_ssid_ifneed(padapter, bssid, pframe);
- RTW_DBG_DUMP("Invalidated EXT Support Rate IE --", p, len+2);
- return _FAIL;
- }
- _rtw_memcpy(bssid->SupportedRates + i, (p + 2), len);
- }
- /* todo: */
- #if 0
- if (judge_network_type(bssid->SupportedRates, (len + i)) == WIRELESS_11B)
- bssid->NetworkTypeInUse = Ndis802_11DS;
- else
- #endif
- {
- bssid->NetworkTypeInUse = Ndis802_11OFDM24;
- }
- #ifdef CONFIG_P2P
- if (subtype == WIFI_PROBEREQ) {
- u8 *p2p_ie;
- u32 p2p_ielen;
- /* Set Listion Channel */
- p2p_ie = rtw_get_p2p_ie(bssid->IEs, bssid->IELength, NULL, &p2p_ielen);
- if (p2p_ie) {
- u32 attr_contentlen = 0;
- u8 listen_ch[5] = { 0x00 };
- rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, listen_ch, &attr_contentlen);
- bssid->Configuration.DSConfig = listen_ch[4];
- } else {
- /* use current channel */
- bssid->Configuration.DSConfig = padapter->mlmeextpriv.cur_channel;
- RTW_INFO("%s()-%d: Cannot get p2p_ie. set DSconfig to op_ch(%d)\n", __FUNCTION__, __LINE__, bssid->Configuration.DSConfig);
- }
- /* FIXME */
- bssid->InfrastructureMode = Ndis802_11Infrastructure;
- _rtw_memcpy(bssid->MacAddress, get_addr2_ptr(pframe), ETH_ALEN);
- bssid->Privacy = 1;
- return _SUCCESS;
- }
- #endif /* CONFIG_P2P */
- if (bssid->IELength < 12)
- return _FAIL;
- /* Checking for DSConfig */
- p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
- bssid->Configuration.DSConfig = 0;
- bssid->Configuration.Length = 0;
- if (p)
- bssid->Configuration.DSConfig = *(p + 2);
- else {
- /* In 5G, some ap do not have DSSET IE */
- /* checking HT info for channel */
- p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
- if (p) {
- struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
- bssid->Configuration.DSConfig = HT_info->primary_channel;
- } else {
- /* use current channel */
- bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
- }
- }
- _rtw_memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
- bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
- val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid);
- if ((val16 & 0x03) == cap_ESS) {
- bssid->InfrastructureMode = Ndis802_11Infrastructure;
- _rtw_memcpy(bssid->MacAddress, get_addr2_ptr(pframe), ETH_ALEN);
- } else if ((val16 & 0x03) == cap_IBSS){
- bssid->InfrastructureMode = Ndis802_11IBSS;
- _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
- } else if ((val16 & 0x03) == 0x00){
- u8 *mesh_id_ie, *mesh_conf_ie;
- sint mesh_id_ie_len, mesh_conf_ie_len;
- mesh_id_ie = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_MESH_ID, &mesh_id_ie_len, bssid->IELength - ie_offset);
- mesh_conf_ie = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_MESH_CONFIG, &mesh_conf_ie_len, bssid->IELength - ie_offset);
- if (mesh_id_ie || mesh_conf_ie) {
- if (!mesh_id_ie) {
- RTW_INFO("cannot find Mesh ID for survey event\n");
- return _FAIL;
- }
- if (mesh_id_ie_len) {
- if (mesh_id_ie_len > NDIS_802_11_LENGTH_SSID) {
- RTW_INFO("Mesh ID too long (%d) for survey event\n", mesh_id_ie_len);
- return _FAIL;
- }
- _rtw_memcpy(bssid->mesh_id.Ssid, (mesh_id_ie + 2), mesh_id_ie_len);
- bssid->mesh_id.SsidLength = mesh_id_ie_len;
- } else
- bssid->mesh_id.SsidLength = 0;
- if (!mesh_conf_ie) {
- RTW_INFO("cannot find Mesh config for survey event\n");
- return _FAIL;
- }
- if (mesh_conf_ie_len != 7) {
- RTW_INFO("invalid Mesh conf IE len (%d) for survey event\n", mesh_conf_ie_len);
- return _FAIL;
- }
- bssid->InfrastructureMode = Ndis802_11_mesh;
- _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
- } else {
- /* default cases */
- bssid->InfrastructureMode = Ndis802_11IBSS;
- _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
- }
- }
- if (val16 & BIT(4))
- bssid->Privacy = 1;
- else
- bssid->Privacy = 0;
- bssid->Configuration.ATIMWindow = 0;
- /* 20/40 BSS Coexistence check */
- if ((pregistrypriv->wifi_spec == 1) && (_FALSE == pmlmeinfo->bwmode_updated)) {
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- #ifdef CONFIG_80211N_HT
- p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
- if (p && len > 0) {
- struct HT_caps_element *pHT_caps;
- pHT_caps = (struct HT_caps_element *)(p + 2);
- if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14))
- pmlmepriv->num_FortyMHzIntolerant++;
- } else
- pmlmepriv->num_sta_no_ht++;
- #endif /* CONFIG_80211N_HT */
- }
- #ifdef CONFIG_INTEL_WIDI
- /* process_intel_widi_query_or_tigger(padapter, bssid); */
- if (process_intel_widi_query_or_tigger(padapter, bssid))
- return _FAIL;
- #endif /* CONFIG_INTEL_WIDI */
- #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1
- if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
- RTW_INFO("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
- , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
- , rtw_get_oper_ch(padapter)
- , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
- );
- }
- #endif
- /* mark bss info receving from nearby channel as SignalQuality 101 */
- if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
- bssid->PhyInfo.SignalQuality = 101;
- #ifdef CONFIG_RTW_80211K
- p = rtw_get_ie(bssid->IEs + ie_offset, _EID_RRM_EN_CAP_IE_, &len, bssid->IELength - ie_offset);
- if (p)
- _rtw_memcpy(bssid->PhyInfo.rm_en_cap, (p + 2), *(p + 1));
- /* save freerun counter */
- bssid->PhyInfo.free_cnt = precv_frame->u.hdr.attrib.free_cnt;
- #endif
- return _SUCCESS;
- }
- void start_create_ibss(_adapter *padapter)
- {
- unsigned short caps;
- u8 val8;
- u8 join_type;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
- u8 doiqk = _FALSE;
- pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
- pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
- /* update wireless mode */
- update_wireless_mode(padapter);
- /* udpate capability */
- caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
- update_capinfo(padapter, caps);
- if (caps & cap_IBSS) { /* adhoc master */
- /* set_opmode_cmd(padapter, adhoc); */ /* removed */
- val8 = 0xcf;
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
- doiqk = _TRUE;
- rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
- /* switch channel */
- set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
- doiqk = _FALSE;
- rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
- beacon_timing_control(padapter);
- /* set msr to WIFI_FW_ADHOC_STATE */
- pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
- Set_MSR(padapter, (pmlmeinfo->state & 0x3));
- /* issue beacon */
- if (send_beacon(padapter) == _FAIL) {
- report_join_res(padapter, -1, WLAN_STATUS_UNSPECIFIED_FAILURE);
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- } else {
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_ADHOC_STARTED);
- join_type = 0;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
- report_join_res(padapter, 1, WLAN_STATUS_SUCCESS);
- pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
- rtw_indicate_connect(padapter);
- }
- } else {
- RTW_INFO("start_create_ibss, invalid cap:%x\n", caps);
- return;
- }
- /* update bc/mc sta_info */
- update_bmc_sta(padapter);
- }
- void start_clnt_join(_adapter *padapter)
- {
- unsigned short caps;
- u8 val8;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
- int beacon_timeout;
- u8 ASIX_ID[] = {0x00, 0x0E, 0xC6};
- /* update wireless mode */
- update_wireless_mode(padapter);
- /* udpate capability */
- caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
- update_capinfo(padapter, caps);
- /* check if sta is ASIX peer and fix IOT issue if it is. */
- if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) , ASIX_ID , 3)) {
- u8 iot_flag = _TRUE;
- rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag));
- }
- if (caps & cap_ESS) {
- Set_MSR(padapter, WIFI_FW_STATION_STATE);
- val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
- #ifdef CONFIG_WAPI_SUPPORT
- if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI) {
- /* Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey. */
- val8 = 0x4c;
- }
- #endif
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
- #ifdef CONFIG_DEAUTH_BEFORE_CONNECT
- /* Because of AP's not receiving deauth before */
- /* AP may: 1)not response auth or 2)deauth us after link is complete */
- /* issue deauth before issuing auth to deal with the situation */
- /* Commented by Albert 2012/07/21 */
- /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
- {
- #ifdef CONFIG_P2P
- _queue *queue = &(padapter->mlmepriv.scanned_queue);
- _list *head = get_list_head(queue);
- _list *pos = get_next(head);
- struct wlan_network *scanned = NULL;
- u8 ie_offset = 0;
- _irqL irqL;
- bool has_p2p_ie = _FALSE;
- _enter_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
- for (pos = get_next(head); !rtw_end_of_queue_search(head, pos); pos = get_next(pos)) {
- scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
- if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE
- && _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE
- ) {
- ie_offset = (scanned->network.Reserved[0] == BSS_TYPE_PROB_REQ ? 0 : 12);
- if (rtw_get_p2p_ie(scanned->network.IEs + ie_offset, scanned->network.IELength - ie_offset, NULL, NULL))
- has_p2p_ie = _TRUE;
- break;
- }
- }
- _exit_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
- if (scanned == NULL || rtw_end_of_queue_search(head, pos) || has_p2p_ie == _FALSE)
- #endif /* CONFIG_P2P */
- /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
- }
- #endif /* CONFIG_DEAUTH_BEFORE_CONNECT */
- /* here wait for receiving the beacon to start auth */
- /* and enable a timer */
- beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
- set_link_timer(pmlmeext, beacon_timeout);
- _set_timer(&padapter->mlmepriv.assoc_timer,
- (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout);
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_roam(padapter)) {
- rtw_ft_start_clnt_join(padapter);
- } else
- #endif
- {
- rtw_sta_linking_test_set_start();
- pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
- }
- } else if (caps & cap_IBSS) { /* adhoc client */
- Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
- val8 = 0xcf;
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
- beacon_timing_control(padapter);
- pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
- report_join_res(padapter, 1, WLAN_STATUS_SUCCESS);
- } else {
- /* RTW_INFO("marc: invalid cap:%x\n", caps); */
- return;
- }
- }
- void start_clnt_auth(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- _cancel_timer_ex(&pmlmeext->link_timer);
- pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
- pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
- pmlmeinfo->auth_seq = 1;
- pmlmeinfo->reauth_count = 0;
- pmlmeinfo->reassoc_count = 0;
- pmlmeinfo->link_count = 0;
- pmlmeext->retry = 0;
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_roam(padapter)) {
- rtw_ft_set_status(padapter, RTW_FT_AUTHENTICATING_STA);
- RTW_PRINT("start ft auth\n");
- } else
- #endif
- RTW_PRINT("start auth\n");
- issue_auth(padapter, NULL, 0);
- set_link_timer(pmlmeext, REAUTH_TO);
- }
- void start_clnt_assoc(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- _cancel_timer_ex(&pmlmeext->link_timer);
- pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
- pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_roam(padapter))
- issue_reassocreq(padapter);
- else
- #endif
- issue_assocreq(padapter);
- set_link_timer(pmlmeext, REASSOC_TO);
- }
- unsigned int receive_disconnect(_adapter *padapter, unsigned char *MacAddr, unsigned short reason, u8 locally_generated)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
- return _SUCCESS;
- RTW_INFO("%s\n", __FUNCTION__);
- #ifdef CONFIG_RTW_REPEATER_SON
- rtw_rson_do_disconnect(padapter);
- #endif
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
- if (report_del_sta_event(padapter, MacAddr, reason, _TRUE, locally_generated) != _FAIL)
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
- if (report_join_res(padapter, -2, reason) != _FAIL)
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- } else
- RTW_INFO(FUNC_ADPT_FMT" - End to Disconnect\n", FUNC_ADPT_ARG(padapter));
- #ifdef CONFIG_RTW_80211R
- rtw_ft_roam_status_reset(padapter);
- #endif
- #ifdef CONFIG_RTW_WNM
- rtw_wnm_reset_btm_state(padapter);
- #endif
- }
- return _SUCCESS;
- }
- #ifdef CONFIG_80211D
- static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
- struct registry_priv *pregistrypriv;
- struct mlme_ext_priv *pmlmeext;
- RT_CHANNEL_INFO *chplan_new;
- u8 channel;
- u8 i;
- pregistrypriv = &padapter->registrypriv;
- pmlmeext = &padapter->mlmeextpriv;
- /* Adjust channel plan by AP Country IE */
- if (pregistrypriv->enable80211d
- && (!pmlmeext->update_channel_plan_by_ap_done)) {
- u8 *ie, *p;
- u32 len;
- RT_CHANNEL_PLAN chplan_ap;
- RT_CHANNEL_INFO *chplan_sta = NULL;
- u8 country[4];
- u8 fcn; /* first channel number */
- u8 noc; /* number of channel */
- u8 j, k;
- ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
- if (!ie)
- return;
- if (len < 6)
- return;
- ie += 2;
- p = ie;
- ie += len;
- _rtw_memset(country, 0, 4);
- _rtw_memcpy(country, p, 3);
- p += 3;
- RTW_INFO("%s: 802.11d country=%s\n", __FUNCTION__, country);
- i = 0;
- while ((ie - p) >= 3) {
- fcn = *(p++);
- noc = *(p++);
- p++;
- for (j = 0; j < noc; j++) {
- if (fcn <= 14)
- channel = fcn + j; /* 2.4 GHz */
- else
- channel = fcn + j * 4; /* 5 GHz */
- chplan_ap.Channel[i++] = channel;
- }
- }
- chplan_ap.Len = i;
- #ifdef CONFIG_RTW_DEBUG
- i = 0;
- RTW_INFO("%s: AP[%s] channel plan {", __FUNCTION__, bssid->Ssid.Ssid);
- while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) {
- _RTW_INFO("%02d,", chplan_ap.Channel[i]);
- i++;
- }
- _RTW_INFO("}\n");
- #endif
- chplan_sta = rtw_malloc(sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM);
- if (!chplan_sta)
- goto done_update_chplan_from_ap;
- _rtw_memcpy(chplan_sta, rfctl->channel_set, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM);
- #ifdef CONFIG_RTW_DEBUG
- i = 0;
- RTW_INFO("%s: STA channel plan {", __FUNCTION__);
- while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
- _RTW_INFO("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE ? 'p' : 'a');
- i++;
- }
- _RTW_INFO("}\n");
- #endif
- _rtw_memset(rfctl->channel_set, 0, sizeof(rfctl->channel_set));
- chplan_new = rfctl->channel_set;
- i = j = k = 0;
- if (pregistrypriv->wireless_mode & WIRELESS_11G) {
- do {
- if ((i == MAX_CHANNEL_NUM)
- || (chplan_sta[i].ChannelNum == 0)
- || (chplan_sta[i].ChannelNum > 14))
- break;
- if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
- break;
- if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- i++;
- j++;
- k++;
- } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- #if 0
- chplan_new[k].ScanType = chplan_sta[i].ScanType;
- #else
- chplan_new[k].ScanType = SCAN_PASSIVE;
- #endif
- i++;
- k++;
- } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- j++;
- k++;
- }
- } while (1);
- /* change AP not support channel to Passive scan */
- while ((i < MAX_CHANNEL_NUM)
- && (chplan_sta[i].ChannelNum != 0)
- && (chplan_sta[i].ChannelNum <= 14)) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- #if 0
- chplan_new[k].ScanType = chplan_sta[i].ScanType;
- #else
- chplan_new[k].ScanType = SCAN_PASSIVE;
- #endif
- i++;
- k++;
- }
- /* add channel AP supported */
- while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- j++;
- k++;
- }
- } else {
- /* keep original STA 2.4G channel plan */
- while ((i < MAX_CHANNEL_NUM)
- && (chplan_sta[i].ChannelNum != 0)
- && (chplan_sta[i].ChannelNum <= 14)) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- chplan_new[k].ScanType = chplan_sta[i].ScanType;
- i++;
- k++;
- }
- /* skip AP 2.4G channel plan */
- while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
- j++;
- }
- if (pregistrypriv->wireless_mode & WIRELESS_11A) {
- do {
- if ((i >= MAX_CHANNEL_NUM)
- || (chplan_sta[i].ChannelNum == 0))
- break;
- if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
- break;
- if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- i++;
- j++;
- k++;
- } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- #if 0
- chplan_new[k].ScanType = chplan_sta[i].ScanType;
- #else
- chplan_new[k].ScanType = SCAN_PASSIVE;
- #endif
- i++;
- k++;
- } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- j++;
- k++;
- }
- } while (1);
- /* change AP not support channel to Passive scan */
- while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- #if 0
- chplan_new[k].ScanType = chplan_sta[i].ScanType;
- #else
- chplan_new[k].ScanType = SCAN_PASSIVE;
- #endif
- i++;
- k++;
- }
- /* add channel AP supported */
- while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
- chplan_new[k].ChannelNum = chplan_ap.Channel[j];
- chplan_new[k].ScanType = SCAN_ACTIVE;
- j++;
- k++;
- }
- } else {
- /* keep original STA 5G channel plan */
- while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
- chplan_new[k].ScanType = chplan_sta[i].ScanType;
- i++;
- k++;
- }
- }
- pmlmeext->update_channel_plan_by_ap_done = 1;
- #ifdef CONFIG_RTW_DEBUG
- k = 0;
- RTW_INFO("%s: new STA channel plan {", __FUNCTION__);
- while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {
- _RTW_INFO("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE ? 'p' : 'c');
- k++;
- }
- _RTW_INFO("}\n");
- #endif
- #if 0
- /* recover the right channel index */
- channel = chplan_sta[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;
- k = 0;
- while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {
- if (chplan_new[k].ChannelNum == channel) {
- RTW_INFO("%s: change mlme_ext sitesurvey channel index from %d to %d\n",
- __FUNCTION__, pmlmeext->sitesurvey_res.channel_idx, k);
- pmlmeext->sitesurvey_res.channel_idx = k;
- break;
- }
- k++;
- }
- #endif
- done_update_chplan_from_ap:
- if (chplan_sta)
- rtw_mfree(chplan_sta, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM);
- }
- }
- #endif
- /****************************************************************************
- Following are the functions to report events
- *****************************************************************************/
- void report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
- {
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct survey_event *psurvey_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext;
- struct cmd_priv *pcmdpriv;
- /* u8 *pframe = precv_frame->u.hdr.rx_data; */
- /* uint len = precv_frame->u.hdr.len; */
- RT_CHANNEL_INFO *chset = adapter_to_chset(padapter);
- int ch_set_idx = -1;
- if (!padapter)
- return;
- pmlmeext = &padapter->mlmeextpriv;
- pcmdpriv = &padapter->cmdpriv;
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
- return;
- cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- return;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct survey_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- rtw_mfree((u8 *)pevtcmd, cmdsz);
- return;
- }
- #ifdef CONFIG_80211D
- process_80211d(padapter, &psurvey_evt->bss);
- #endif
- ch_set_idx = rtw_chset_search_ch(chset, psurvey_evt->bss.Configuration.DSConfig);
- if (ch_set_idx >= 0) {
- if (psurvey_evt->bss.InfrastructureMode == Ndis802_11Infrastructure) {
- if (chset[ch_set_idx].ScanType == SCAN_PASSIVE
- && !rtw_is_dfs_ch(psurvey_evt->bss.Configuration.DSConfig)
- ) {
- RTW_INFO("%s: change ch:%d to active\n", __func__, psurvey_evt->bss.Configuration.DSConfig);
- chset[ch_set_idx].ScanType = SCAN_ACTIVE;
- }
- #ifdef CONFIG_DFS
- if (hidden_ssid_ap(&psurvey_evt->bss))
- chset[ch_set_idx].hidden_bss_cnt++;
- #endif
- }
- }
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- pmlmeext->sitesurvey_res.bss_cnt++;
- return;
- }
- void report_surveydone_event(_adapter *padapter)
- {
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct surveydone_event *psurveydone_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
- return;
- cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- return;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct surveydone_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
- RTW_INFO("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- return;
- }
- u32 report_join_res(_adapter *padapter, int aid_res, u16 status)
- {
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct joinbss_event *pjoinbss_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u32 ret = _FAIL;
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
- goto exit;
- cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- goto exit;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct joinbss_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- _rtw_memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
- pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = aid_res;
- RTW_INFO("report_join_res(%d, %u)\n", aid_res, status);
- rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network, status);
- ret = rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- exit:
- return ret;
- }
- void report_wmm_edca_update(_adapter *padapter)
- {
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct wmm_event *pwmm_event;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
- return;
- cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- return;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct wmm_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- pwmm_event->wmm = 0;
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- return;
- }
- u32 report_del_sta_event(_adapter *padapter, unsigned char *MacAddr, unsigned short reason, bool enqueue, u8 locally_generated)
- {
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct sta_info *psta;
- int mac_id = -1;
- struct stadel_event *pdel_sta_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- u8 res = _SUCCESS;
- /* prepare cmd parameter */
- cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- res = _FAIL;
- goto exit;
- }
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct stadel_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- _rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
- _rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
- psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
- if (psta)
- mac_id = (int)psta->cmn.mac_id;
- else
- mac_id = (-1);
- pdel_sta_evt->mac_id = mac_id;
- pdel_sta_evt->locally_generated = locally_generated;
- if (!enqueue) {
- /* do directly */
- rtw_stadel_event_callback(padapter, (u8 *)pdel_sta_evt);
- rtw_mfree(pevtcmd, cmdsz);
- } else {
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL) {
- rtw_mfree(pevtcmd, cmdsz);
- res = _FAIL;
- goto exit;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- res = rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- }
- exit:
- RTW_INFO(FUNC_ADPT_FMT" "MAC_FMT" mac_id=%d, enqueue:%d, res:%u\n"
- , FUNC_ADPT_ARG(padapter), MAC_ARG(MacAddr), mac_id, enqueue, res);
- return res;
- }
- void report_add_sta_event(_adapter *padapter, unsigned char *MacAddr)
- {
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct stassoc_event *padd_sta_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
- return;
- cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- return;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct stassoc_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- _rtw_memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
- RTW_INFO("report_add_sta_event: add STA\n");
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- return;
- }
- bool rtw_port_switch_chk(_adapter *adapter)
- {
- bool switch_needed = _FALSE;
- #ifdef CONFIG_CONCURRENT_MODE
- #ifdef CONFIG_RUNTIME_PORT_SWITCH
- struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
- struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj);
- _adapter *if_port0 = NULL;
- _adapter *if_port1 = NULL;
- struct mlme_ext_info *if_port0_mlmeinfo = NULL;
- struct mlme_ext_info *if_port1_mlmeinfo = NULL;
- int i;
- for (i = 0; i < dvobj->iface_nums; i++) {
- if (get_hw_port(dvobj->padapters[i]) == HW_PORT0) {
- if_port0 = dvobj->padapters[i];
- if_port0_mlmeinfo = &(if_port0->mlmeextpriv.mlmext_info);
- } else if (get_hw_port(dvobj->padapters[i]) == HW_PORT1) {
- if_port1 = dvobj->padapters[i];
- if_port1_mlmeinfo = &(if_port1->mlmeextpriv.mlmext_info);
- }
- }
- if (if_port0 == NULL) {
- rtw_warn_on(1);
- goto exit;
- }
- if (if_port1 == NULL) {
- rtw_warn_on(1);
- goto exit;
- }
- #ifdef DBG_RUNTIME_PORT_SWITCH
- RTW_INFO(FUNC_ADPT_FMT" wowlan_mode:%u\n"
- ADPT_FMT", port0, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n"
- ADPT_FMT", port1, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n",
- FUNC_ADPT_ARG(adapter), pwrctl->wowlan_mode,
- ADPT_ARG(if_port0), if_port0_mlmeinfo->state, rtw_p2p_state(&if_port0->wdinfo), rtw_p2p_chk_state(&if_port0->wdinfo, P2P_STATE_NONE),
- ADPT_ARG(if_port1), if_port1_mlmeinfo->state, rtw_p2p_state(&if_port1->wdinfo), rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE));
- #endif /* DBG_RUNTIME_PORT_SWITCH */
- #ifdef CONFIG_WOWLAN
- /* WOWLAN interface(primary, for now) should be port0 */
- if (pwrctl->wowlan_mode == _TRUE) {
- if (!is_primary_adapter(if_port0)) {
- RTW_INFO("%s "ADPT_FMT" enable WOWLAN\n", __func__, ADPT_ARG(if_port1));
- switch_needed = _TRUE;
- }
- goto exit;
- }
- #endif /* CONFIG_WOWLAN */
- /* AP/Mesh should use port0 for ctl frame's ack */
- if ((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
- RTW_INFO("%s "ADPT_FMT" is AP/GO/Mesh\n", __func__, ADPT_ARG(if_port1));
- switch_needed = _TRUE;
- goto exit;
- }
- /* GC should use port0 for p2p ps */
- if (((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
- && (if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
- #ifdef CONFIG_P2P
- && !rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE)
- #endif
- && !check_fwstate(&if_port1->mlmepriv, WIFI_UNDER_WPS)
- ) {
- RTW_INFO("%s "ADPT_FMT" is GC\n", __func__, ADPT_ARG(if_port1));
- switch_needed = _TRUE;
- goto exit;
- }
- /* port1 linked, but port0 not linked */
- if ((if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
- && !(if_port0_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
- && ((if_port0_mlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
- ) {
- RTW_INFO("%s "ADPT_FMT" is SINGLE_LINK\n", __func__, ADPT_ARG(if_port1));
- switch_needed = _TRUE;
- goto exit;
- }
- exit:
- #ifdef DBG_RUNTIME_PORT_SWITCH
- RTW_INFO(FUNC_ADPT_FMT" ret:%d\n", FUNC_ADPT_ARG(adapter), switch_needed);
- #endif /* DBG_RUNTIME_PORT_SWITCH */
- #endif /* CONFIG_RUNTIME_PORT_SWITCH */
- #endif /* CONFIG_CONCURRENT_MODE */
- return switch_needed;
- }
- /****************************************************************************
- Following are the event callback functions
- *****************************************************************************/
- /* for sta/adhoc mode */
- void update_sta_info(_adapter *padapter, struct sta_info *psta)
- {
- _irqL irqL;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- /* ERP */
- VCS_update(padapter, psta);
- #ifdef CONFIG_80211N_HT
- /* HT */
- if (pmlmepriv->htpriv.ht_option) {
- psta->htpriv.ht_option = _TRUE;
- psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
- psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
- if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
- psta->htpriv.sgi_20m = _TRUE;
- if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
- psta->htpriv.sgi_40m = _TRUE;
- psta->qos_option = _TRUE;
- psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
- psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
- psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
- _rtw_memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));
- #ifdef CONFIG_BEAMFORMING
- psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
- psta->cmn.bf_info.ht_beamform_cap = pmlmepriv->htpriv.beamform_cap;
- #endif
- } else
- #endif /* CONFIG_80211N_HT */
- {
- #ifdef CONFIG_80211N_HT
- psta->htpriv.ht_option = _FALSE;
- psta->htpriv.ampdu_enable = _FALSE;
- psta->htpriv.tx_amsdu_enable = _FALSE;
- psta->htpriv.sgi_20m = _FALSE;
- psta->htpriv.sgi_40m = _FALSE;
- #endif /* CONFIG_80211N_HT */
- psta->qos_option = _FALSE;
- }
- #ifdef CONFIG_80211N_HT
- psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
- psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
- psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
- #endif /* CONFIG_80211N_HT */
- psta->cmn.bw_mode = pmlmeext->cur_bwmode;
- /* QoS */
- if (pmlmepriv->qospriv.qos_option)
- psta->qos_option = _TRUE;
- #ifdef CONFIG_80211AC_VHT
- _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
- if (psta->vhtpriv.vht_option) {
- psta->cmn.ra_info.is_vht_enable = _TRUE;
- #ifdef CONFIG_BEAMFORMING
- psta->vhtpriv.beamform_cap = pmlmepriv->vhtpriv.beamform_cap;
- psta->cmn.bf_info.vht_beamform_cap = pmlmepriv->vhtpriv.beamform_cap;
- #endif /*CONFIG_BEAMFORMING*/
- }
- #endif /* CONFIG_80211AC_VHT */
- psta->cmn.ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta));
- update_ldpc_stbc_cap(psta);
- _enter_critical_bh(&psta->lock, &irqL);
- psta->state = _FW_LINKED;
- _exit_critical_bh(&psta->lock, &irqL);
- }
- static void rtw_mlmeext_disconnect(_adapter *padapter)
- {
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 self_action = MLME_ACTION_UNKNOWN;
- u8 state_backup = (pmlmeinfo->state & 0x03);
- u8 ASIX_ID[] = {0x00, 0x0E, 0xC6};
- if (MLME_IS_AP(padapter))
- self_action = MLME_AP_STOPPED;
- else if (MLME_IS_MESH(padapter))
- self_action = MLME_MESH_STOPPED;
- else if (MLME_IS_STA(padapter))
- self_action = MLME_STA_DISCONNECTED;
- else if (MLME_IS_ADHOC(padapter) || MLME_IS_ADHOC_MASTER(padapter))
- self_action = MLME_ADHOC_STOPPED;
- else {
- RTW_INFO("state:0x%x\n", MLME_STATE(padapter));
- rtw_warn_on(1);
- }
- /* set_opmode_cmd(padapter, infra_client_with_mlme); */
- #ifdef CONFIG_HW_P0_TSF_SYNC
- if (self_action == MLME_STA_DISCONNECTED)
- correct_TSF(padapter, self_action);
- #endif
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
- if (self_action == MLME_STA_DISCONNECTED)
- rtw_hal_rcr_set_chk_bssid(padapter, self_action);
- /* set MSR to no link state->infra. mode */
- Set_MSR(padapter, _HW_STATE_STATION_);
- /* check if sta is ASIX peer and fix IOT issue if it is. */
- if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) , ASIX_ID , 3)) {
- u8 iot_flag = _FALSE;
- rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag));
- }
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- #ifdef CONFIG_MCC_MODE
- /* mcc disconnect setting before download LPS rsvd page */
- rtw_hal_set_mcc_setting_disconnect(padapter);
- #endif /* CONFIG_MCC_MODE */
- if (state_backup == WIFI_FW_STATION_STATE) {
- if (rtw_port_switch_chk(padapter) == _TRUE) {
- rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
- #ifdef CONFIG_LPS
- {
- _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
- if (port0_iface)
- rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
- }
- #endif
- }
- }
- /* switch to the 20M Hz mode after disconnect */
- pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- #ifdef CONFIG_FCS_MODE
- if (EN_FCS(padapter))
- rtw_hal_set_hwreg(padapter, HW_VAR_STOP_FCS_MODE, NULL);
- #endif
- if (!(MLME_IS_STA(padapter) && MLME_IS_OPCH_SW(padapter))) {
- /* DFS and channel status no need to check here for STA under OPCH_SW */
- u8 ch, bw, offset;
- #ifdef CONFIG_DFS_MASTER
- rtw_dfs_rd_en_decision(padapter, self_action, 0);
- #endif
- if (rtw_mi_get_ch_setting_union_no_self(padapter, &ch, &bw, &offset) != 0) {
- set_channel_bwmode(padapter, ch, offset, bw);
- rtw_mi_update_union_chan_inf(padapter, ch, offset, bw);
- }
- }
- flush_all_cam_entry(padapter);
- _cancel_timer_ex(&pmlmeext->link_timer);
- /* pmlmepriv->LinkDetectInfo.TrafficBusyState = _FALSE; */
- pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
- pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
- #ifdef CONFIG_TDLS
- padapter->tdlsinfo.ap_prohibited = _FALSE;
- /* For TDLS channel switch, currently we only allow it to work in wifi logo test mode */
- if (padapter->registrypriv.wifi_spec == 1)
- padapter->tdlsinfo.ch_switch_prohibited = _FALSE;
- #endif /* CONFIG_TDLS */
- #ifdef CONFIG_WMMPS_STA
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- /* reset currently related uapsd setting when the connection has broken */
- pmlmepriv->qospriv.uapsd_max_sp_len = 0;
- pmlmepriv->qospriv.uapsd_tid = 0;
- pmlmepriv->qospriv.uapsd_tid_delivery_enabled = 0;
- pmlmepriv->qospriv.uapsd_tid_trigger_enabled = 0;
- pmlmepriv->qospriv.uapsd_ap_supported = 0;
- }
- #endif /* CONFIG_WMMPS_STA */
- }
- void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res)
- {
- struct sta_info *psta;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 join_type;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- #ifndef CONFIG_IOCTL_CFG80211
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- #endif
- if (pmlmepriv->wpa_phase == _TRUE)
- pmlmepriv->wpa_phase = _FALSE;
- if (join_res < 0) {
- join_type = 1;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_DISCONNECTED);
- goto exit_mlmeext_joinbss_event_callback;
- }
- #ifdef CONFIG_ARP_KEEP_ALIVE
- pmlmepriv->bGetGateway = 1;
- pmlmepriv->GetGatewayTryCnt = 0;
- #endif
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- /* update bc/mc sta_info */
- update_bmc_sta(padapter);
- }
- /* turn on dynamic functions */
- /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE); */
- /* update IOT-releated issue */
- update_IOT_info(padapter);
- rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
- /* BCN interval */
- rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
- /* udpate capability */
- update_capinfo(padapter, pmlmeinfo->capability);
- /* WMM, Update EDCA param */
- WMMOnAssocRsp(padapter);
- #ifdef CONFIG_80211N_HT
- /* HT */
- HTOnAssocRsp(padapter);
- #endif /* CONFIG_80211N_HT */
- #ifdef CONFIG_80211AC_VHT
- /* VHT */
- VHTOnAssocRsp(padapter);
- #endif
- psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
- if (psta) { /* only for infra. mode */
- psta->wireless_mode = pmlmeext->cur_wireless_mode;
- /* set per sta rate after updating HT cap. */
- set_sta_rate(padapter, psta);
- rtw_sta_media_status_rpt(padapter, psta, 1);
- /* wakeup macid after join bss successfully to ensure
- the subsequent data frames can be sent out normally */
- rtw_hal_macid_wakeup(padapter, psta->cmn.mac_id);
- }
- #ifndef CONFIG_IOCTL_CFG80211
- if (is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm))
- rtw_sec_restore_wep_key(padapter);
- #endif /* CONFIG_IOCTL_CFG80211 */
- if (rtw_port_switch_chk(padapter) == _TRUE)
- rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
- join_type = 2;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_CONNECTED);
- /* correcting TSF */
- correct_TSF(padapter, MLME_STA_CONNECTED);
- /* set_link_timer(pmlmeext, DISCONNECT_TO); */
- }
- #ifdef CONFIG_LPS
- #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
- if (get_hw_port(padapter) == HW_PORT0)
- #endif
- rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
- #endif
- #ifdef CONFIG_BEAMFORMING
- if (psta)
- beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_ENTER, (u8 *)psta, sizeof(struct sta_info), 0);
- #endif/*CONFIG_BEAMFORMING*/
- exit_mlmeext_joinbss_event_callback:
- rtw_join_done_chk_ch(padapter, join_res);
- #ifdef CONFIG_RTW_REPEATER_SON
- rtw_rson_join_done(padapter);
- #endif
- RTW_INFO("=>%s - End to Connection without 4-way\n", __FUNCTION__);
- }
- /* currently only adhoc mode will go here */
- void mlmeext_sta_add_event_callback(_adapter *padapter, struct sta_info *psta)
- {
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 join_type;
- RTW_INFO("%s\n", __FUNCTION__);
- if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */
- /* nothing to do */
- } else { /* adhoc client */
- /* update TSF Value */
- /* update_TSF(pmlmeext, pframe, len); */
- /* correcting TSF */
- correct_TSF(padapter, MLME_ADHOC_STARTED);
- /* start beacon */
- if (send_beacon(padapter) == _FAIL)
- rtw_warn_on(1);
- pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
- }
- join_type = 2;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
- }
- /* update adhoc sta_info */
- update_sta_info(padapter, psta);
- rtw_hal_update_sta_ra_info(padapter, psta);
- /* ToDo: HT for Ad-hoc */
- psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
- rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
- /* rate radaptive */
- Update_RA_Entry(padapter, psta);
- }
- void mlmeext_sta_del_event_callback(_adapter *padapter)
- {
- if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
- rtw_mlmeext_disconnect(padapter);
- }
- /****************************************************************************
- Following are the functions for the timer handlers
- *****************************************************************************/
- void _linked_info_dump(_adapter *padapter)
- {
- if (padapter->bLinkInfoDump) {
- rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, RTW_DBGDUMP);
- rtw_hal_set_odm_var(padapter, HAL_ODM_RX_INFO_DUMP, RTW_DBGDUMP, _FALSE);
- }
- }
- /********************************************************************
- When station does not receive any packet in MAX_CONTINUAL_NORXPACKET_COUNT*2 seconds,
- recipient station will teardown the block ack by issuing DELBA frame.
- *********************************************************************/
- void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer)
- {
- int i = 0;
- int ret = _SUCCESS;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- /*
- IOT issue,occur Broadcom ap(Buffalo WZR-D1800H,Netgear R6300).
- AP is originator.AP does not transmit unicast packets when STA response its BAR.
- This case probably occur ap issue BAR after AP builds BA.
- Follow 802.11 spec, STA shall maintain an inactivity timer for every negotiated Block Ack setup.
- The inactivity timer is not reset when MPDUs corresponding to other TIDs are received.
- */
- if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM) {
- for (i = 0; i < TID_NUM ; i++) {
- if ((psta->recvreorder_ctrl[i].enable) &&
- (sta_rx_data_qos_pkts(psta, i) == sta_last_rx_data_qos_pkts(psta, i)) ) {
- if (_TRUE == rtw_inc_and_chk_continual_no_rx_packet(psta, i)) {
- /* send a DELBA frame to the peer STA with the Reason Code field set to TIMEOUT */
- if (!from_timer)
- ret = issue_del_ba_ex(padapter, psta->cmn.mac_addr, i, 39, 0, 3, 1);
- else
- issue_del_ba(padapter, psta->cmn.mac_addr, i, 39, 0);
- psta->recvreorder_ctrl[i].enable = _FALSE;
- if (ret != _FAIL)
- psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID;
- rtw_reset_continual_no_rx_packet(psta, i);
- }
- } else {
- /* The inactivity timer is reset when MPDUs to the TID is received. */
- rtw_reset_continual_no_rx_packet(psta, i);
- }
- }
- }
- }
- u8 chk_ap_is_alive(_adapter *padapter, struct sta_info *psta)
- {
- u8 ret = _FALSE;
- #ifdef DBG_EXPIRATION_CHK
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- RTW_INFO(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
- /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
- ", retry:%u\n"
- , FUNC_ADPT_ARG(padapter)
- , STA_RX_PKTS_DIFF_ARG(psta)
- , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
- , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
- /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
- , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
- , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
- , pmlmeinfo->bcn_interval*/
- , pmlmeext->retry
- );
- RTW_INFO(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
- , sta_tx_pkts(psta)
- , pmlmeinfo->link_count
- );
- #endif
- if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
- && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
- && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
- )
- ret = _FALSE;
- else
- ret = _TRUE;
- sta_update_last_rx_pkts(psta);
- return ret;
- }
- u8 chk_adhoc_peer_is_alive(struct sta_info *psta)
- {
- u8 ret = _TRUE;
- #ifdef DBG_EXPIRATION_CHK
- RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
- /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
- ", expire_to:%u\n"
- , MAC_ARG(psta->cmn.mac_addr)
- , psta->cmn.rssi_stat.rssi
- , STA_RX_PKTS_DIFF_ARG(psta)
- , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
- , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
- /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
- , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
- , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
- , pmlmeinfo->bcn_interval*/
- , psta->expire_to
- );
- #endif
- if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)
- && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
- && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
- ret = _FALSE;
- sta_update_last_rx_pkts(psta);
- return ret;
- }
- #ifdef CONFIG_TDLS
- u8 chk_tdls_peer_sta_is_alive(_adapter *padapter, struct sta_info *psta)
- {
- if ((psta->sta_stats.rx_data_pkts == psta->sta_stats.last_rx_data_pkts)
- && (psta->sta_stats.rx_tdls_disc_rsp_pkts == psta->sta_stats.last_rx_tdls_disc_rsp_pkts))
- return _FALSE;
- return _TRUE;
- }
- void linked_status_chk_tdls(_adapter *padapter)
- {
- struct candidate_pool {
- struct sta_info *psta;
- u8 addr[ETH_ALEN];
- };
- struct sta_priv *pstapriv = &padapter->stapriv;
- _irqL irqL;
- u8 ack_chk;
- struct sta_info *psta;
- int i, num_teardown = 0, num_checkalive = 0;
- _list *plist, *phead;
- struct tdls_txmgmt txmgmt;
- struct candidate_pool checkalive[MAX_ALLOWED_TDLS_STA_NUM];
- struct candidate_pool teardown[MAX_ALLOWED_TDLS_STA_NUM];
- u8 tdls_sta_max = _FALSE;
- #define ALIVE_MIN 2
- #define ALIVE_MAX 5
- _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
- _rtw_memset(checkalive, 0x00, sizeof(checkalive));
- _rtw_memset(teardown, 0x00, sizeof(teardown));
- if ((padapter->tdlsinfo.link_established == _TRUE)) {
- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
- for (i = 0; i < NUM_STA; i++) {
- phead = &(pstapriv->sta_hash[i]);
- plist = get_next(phead);
- while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
- psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
- plist = get_next(plist);
- if (psta->tdls_sta_state & TDLS_LINKED_STATE) {
- psta->alive_count++;
- if (psta->alive_count >= ALIVE_MIN) {
- if (chk_tdls_peer_sta_is_alive(padapter, psta) == _FALSE) {
- if (psta->alive_count < ALIVE_MAX) {
- _rtw_memcpy(checkalive[num_checkalive].addr, psta->cmn.mac_addr, ETH_ALEN);
- checkalive[num_checkalive].psta = psta;
- num_checkalive++;
- } else {
- _rtw_memcpy(teardown[num_teardown].addr, psta->cmn.mac_addr, ETH_ALEN);
- teardown[num_teardown].psta = psta;
- num_teardown++;
- }
- } else
- psta->alive_count = 0;
- }
- psta->sta_stats.last_rx_data_pkts = psta->sta_stats.rx_data_pkts;
- psta->sta_stats.last_rx_tdls_disc_rsp_pkts = psta->sta_stats.rx_tdls_disc_rsp_pkts;
- if ((num_checkalive >= MAX_ALLOWED_TDLS_STA_NUM) || (num_teardown >= MAX_ALLOWED_TDLS_STA_NUM)) {
- tdls_sta_max = _TRUE;
- break;
- }
- }
- }
- if (tdls_sta_max == _TRUE)
- break;
- }
- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
- if (num_checkalive > 0) {
- for (i = 0; i < num_checkalive; i++) {
- _rtw_memcpy(txmgmt.peer, checkalive[i].addr, ETH_ALEN);
- issue_tdls_dis_req(padapter, &txmgmt);
- issue_tdls_dis_req(padapter, &txmgmt);
- issue_tdls_dis_req(padapter, &txmgmt);
- }
- }
- if (num_teardown > 0) {
- for (i = 0; i < num_teardown; i++) {
- RTW_INFO("[%s %d] Send teardown to "MAC_FMT"\n", __FUNCTION__, __LINE__, MAC_ARG(teardown[i].addr));
- txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;
- _rtw_memcpy(txmgmt.peer, teardown[i].addr, ETH_ALEN);
- issue_tdls_teardown(padapter, &txmgmt, _FALSE);
- }
- }
- }
- }
- #endif /* CONFIG_TDLS */
- /* from_timer == 1 means driver is in LPS */
- void linked_status_chk(_adapter *padapter, u8 from_timer)
- {
- u32 i;
- struct sta_info *psta;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct sta_priv *pstapriv = &padapter->stapriv;
- #if defined(CONFIG_ARP_KEEP_ALIVE) || defined(CONFIG_LAYER2_ROAMING)
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- #endif
- #ifdef CONFIG_LAYER2_ROAMING
- struct recv_priv *precvpriv = &padapter->recvpriv;
- #endif
- if (padapter->registrypriv.mp_mode == _TRUE)
- return;
- if (is_client_associated_to_ap(padapter)) {
- /* linked infrastructure client mode */
- int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
- int rx_chk_limit;
- int link_count_limit;
- #if defined(CONFIG_RTW_REPEATER_SON)
- rtw_rson_scan_wk_cmd(padapter, RSON_SCAN_PROCESS);
- #elif defined(CONFIG_LAYER2_ROAMING)
- if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE)) {
- RTW_INFO("signal_strength_data.avg_val = %d\n", precvpriv->signal_strength_data.avg_val);
- if ((precvpriv->signal_strength_data.avg_val < pmlmepriv->roam_rssi_threshold)
- && (rtw_get_passing_time_ms(pmlmepriv->last_roaming) >= pmlmepriv->roam_scan_int*2000)) {
- #ifdef CONFIG_RTW_80211K
- rtw_roam_nb_discover(padapter, _FALSE);
- #endif
- pmlmepriv->need_to_roam = _TRUE;
- rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM);
- pmlmepriv->last_roaming = rtw_get_current_time();
- } else
- pmlmepriv->need_to_roam = _FALSE;
- }
- #endif
- #ifdef CONFIG_MCC_MODE
- /*
- * due to tx ps null date to ao, so ap doest not tx pkt to driver
- * we may check chk_ap_is_alive fail, and may issue_probereq to wrong channel under sitesurvey
- * don't keep alive check under MCC
- */
- if (rtw_hal_mcc_link_status_chk(padapter, __func__) == _FALSE)
- return;
- #endif
- #if defined(DBG_ROAMING_TEST) || defined(CONFIG_RTW_REPEATER_SON)
- rx_chk_limit = 1;
- #elif defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER)
- rx_chk_limit = 4;
- #else
- rx_chk_limit = 8;
- #endif
- #ifdef CONFIG_ARP_KEEP_ALIVE
- if (!from_timer && pmlmepriv->bGetGateway == 1 && pmlmepriv->GetGatewayTryCnt < 3) {
- RTW_INFO("do rtw_gw_addr_query() : %d\n", pmlmepriv->GetGatewayTryCnt);
- pmlmepriv->GetGatewayTryCnt++;
- if (rtw_gw_addr_query(padapter) == 0)
- pmlmepriv->bGetGateway = 0;
- else {
- _rtw_memset(pmlmepriv->gw_ip, 0, 4);
- _rtw_memset(pmlmepriv->gw_mac_addr, 0, ETH_ALEN);
- }
- }
- #endif
- #ifdef CONFIG_P2P
- if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {
- if (!from_timer)
- link_count_limit = 3; /* 8 sec */
- else
- link_count_limit = 15; /* 32 sec */
- } else
- #endif /* CONFIG_P2P */
- {
- if (!from_timer)
- link_count_limit = 7; /* 16 sec */
- else
- link_count_limit = 29; /* 60 sec */
- }
- #ifdef CONFIG_TDLS
- #ifdef CONFIG_TDLS_CH_SW
- if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) == _TRUE)
- return;
- #endif /* CONFIG_TDLS_CH_SW */
- #ifdef CONFIG_TDLS_AUTOCHECKALIVE
- linked_status_chk_tdls(padapter);
- #endif /* CONFIG_TDLS_AUTOCHECKALIVE */
- #endif /* CONFIG_TDLS */
- psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
- if (psta != NULL) {
- bool is_p2p_enable = _FALSE;
- #ifdef CONFIG_P2P
- is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
- #endif
- #ifdef CONFIG_ISSUE_DELBA_WHEN_NO_TRAFFIC
- /*issue delba when ap does not tx data packet that is Broadcom ap */
- rtw_delba_check(padapter, psta, from_timer);
- #endif
- if (chk_ap_is_alive(padapter, psta) == _FALSE)
- rx_chk = _FAIL;
- if (sta_last_tx_pkts(psta) == sta_tx_pkts(psta))
- tx_chk = _FAIL;
- #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
- if (!from_timer && pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)
- ) {
- u8 backup_ch = 0, backup_bw = 0, backup_offset = 0;
- u8 union_ch = 0, union_bw = 0, union_offset = 0;
- u8 switch_channel_by_drv = _TRUE;
-
- #ifdef CONFIG_MCC_MODE
- if (MCC_EN(padapter)) {
- /* driver doesn't switch channel under MCC */
- if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
- switch_channel_by_drv = _FALSE;
- }
- #endif
- if (switch_channel_by_drv) {
- if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)
- || pmlmeext->cur_channel != union_ch)
- goto bypass_active_keep_alive;
- /* switch to correct channel of current network before issue keep-alive frames */
- if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
- backup_ch = rtw_get_oper_ch(padapter);
- backup_bw = rtw_get_oper_bw(padapter);
- backup_offset = rtw_get_oper_choffset(padapter);
- set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
- }
- }
- if (rx_chk != _SUCCESS)
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->cmn.mac_addr, 0, 0, 3, 1);
- if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) || rx_chk != _SUCCESS) {
- if (rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY))
- tx_chk = issue_nulldata(padapter, psta->cmn.mac_addr, 1, 3, 1);
- else
- tx_chk = issue_nulldata(padapter, psta->cmn.mac_addr, 0, 3, 1);
- /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
- if (tx_chk == _SUCCESS && !is_p2p_enable)
- rx_chk = _SUCCESS;
- }
- /* back to the original operation channel */
- if (backup_ch > 0 && switch_channel_by_drv)
- set_channel_bwmode(padapter, backup_ch, backup_offset, backup_bw);
- bypass_active_keep_alive:
- ;
- } else
- #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
- {
- if (rx_chk != _SUCCESS) {
- if (pmlmeext->retry == 0) {
- #ifdef DBG_EXPIRATION_CHK
- RTW_INFO("issue_probereq to trigger probersp, retry=%d\n", pmlmeext->retry);
- #endif
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1));
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1));
- issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1));
- }
- }
- if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit
- #ifdef CONFIG_MCC_MODE
- /* FW tx nulldata under MCC mode, we just check ap is alive */
- && (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC))
- #endif /* CONFIG_MCC_MODE */
- ) {
- #ifdef DBG_EXPIRATION_CHK
- RTW_INFO("%s issue_nulldata(%d)\n", __FUNCTION__, from_timer ? 1 : 0);
- #endif
- if (from_timer || rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY))
- tx_chk = issue_nulldata(padapter, NULL, 1, 0, 0);
- else
- tx_chk = issue_nulldata(padapter, NULL, 0, 1, 1);
- }
- }
- if (rx_chk == _FAIL) {
- pmlmeext->retry++;
- if (pmlmeext->retry > rx_chk_limit) {
- RTW_PRINT(FUNC_ADPT_FMT" disconnect or roaming\n",
- FUNC_ADPT_ARG(padapter));
- receive_disconnect(padapter, pmlmeinfo->network.MacAddress
- , WLAN_REASON_EXPIRATION_CHK, _FALSE);
- return;
- }
- } else
- pmlmeext->retry = 0;
- if (tx_chk == _FAIL)
- pmlmeinfo->link_count %= (link_count_limit + 1);
- else {
- psta->sta_stats.last_tx_pkts = psta->sta_stats.tx_pkts;
- pmlmeinfo->link_count = 0;
- }
- } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
- } else if (is_client_associated_to_ibss(padapter)) {
- _irqL irqL;
- _list *phead, *plist, dlist;
- _rtw_init_listhead(&dlist);
- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
- for (i = 0; i < NUM_STA; i++) {
- phead = &(pstapriv->sta_hash[i]);
- plist = get_next(phead);
- while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
- psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
- plist = get_next(plist);
- if (is_broadcast_mac_addr(psta->cmn.mac_addr))
- continue;
- if (chk_adhoc_peer_is_alive(psta) || !psta->expire_to)
- psta->expire_to = pstapriv->adhoc_expire_to;
- else
- psta->expire_to--;
- if (psta->expire_to <= 0) {
- rtw_list_delete(&psta->list);
- rtw_list_insert_tail(&psta->list, &dlist);
- }
- }
- }
- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
- plist = get_next(&dlist);
- while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
- psta = LIST_CONTAINOR(plist, struct sta_info, list);
- plist = get_next(plist);
- rtw_list_delete(&psta->list);
- RTW_INFO(FUNC_ADPT_FMT" ibss expire "MAC_FMT"\n"
- , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));
- report_del_sta_event(padapter, psta->cmn.mac_addr, WLAN_REASON_EXPIRATION_CHK, from_timer ? _TRUE : _FALSE, _FALSE);
- }
- }
- }
- void survey_timer_hdl(void *ctx)
- {
- _adapter *padapter = (_adapter *)ctx;
- struct cmd_obj *cmd;
- struct sitesurvey_parm *psurveyPara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- if (mlmeext_scan_state(pmlmeext) > SCAN_DISABLE) {
- cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (cmd == NULL) {
- rtw_warn_on(1);
- goto exit;
- }
- psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
- if (psurveyPara == NULL) {
- rtw_warn_on(1);
- rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
- goto exit;
- }
- init_h2fwcmd_w_parm_no_rsp(cmd, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
- rtw_enqueue_cmd(pcmdpriv, cmd);
- }
- exit:
- return;
- }
- #ifdef CONFIG_RTW_REPEATER_SON
- /* 100ms pass, stop rson_scan */
- void rson_timer_hdl(void *ctx)
- {
- _adapter *padapter = (_adapter *)ctx;
- rtw_rson_scan_wk_cmd(padapter, RSON_SCAN_DISABLE);
- }
- #endif
- void link_timer_hdl(void *ctx)
- {
- _adapter *padapter = (_adapter *)ctx;
- /* static unsigned int rx_pkt = 0; */
- /* static u64 tx_cnt = 0; */
- /* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- /* struct sta_priv *pstapriv = &padapter->stapriv; */
- #ifdef CONFIG_RTW_80211R
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *psta = NULL;
- WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
- #endif
- if (rtw_sta_linking_test_force_fail())
- RTW_INFO("rtw_sta_linking_test_force_fail\n");
- if (pmlmeext->join_abort && pmlmeinfo->state != WIFI_FW_NULL_STATE) {
- RTW_INFO(FUNC_ADPT_FMT" join abort\n", FUNC_ADPT_ARG(padapter));
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- report_join_res(padapter, -4, WLAN_STATUS_UNSPECIFIED_FAILURE);
- goto exit;
- }
- if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
- RTW_INFO("link_timer_hdl:no beacon while connecting\n");
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- report_join_res(padapter, -3, WLAN_STATUS_UNSPECIFIED_FAILURE);
- } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
- /* re-auth timer */
- if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
- /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
- /* { */
- pmlmeinfo->state = 0;
- if (pmlmeinfo->auth_status) {
- report_join_res(padapter, -1, pmlmeinfo->auth_status);
- pmlmeinfo->auth_status = 0; /* reset */
- } else
- report_join_res(padapter, -1, WLAN_STATUS_UNSPECIFIED_FAILURE);
- return;
- /* } */
- /* else */
- /* { */
- /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
- /* pmlmeinfo->reauth_count = 0; */
- /* } */
- }
- RTW_INFO("link_timer_hdl: auth timeout and try again\n");
- pmlmeinfo->auth_seq = 1;
- issue_auth(padapter, NULL, 0);
- set_link_timer(pmlmeext, REAUTH_TO);
- } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
- /* re-assoc timer */
- if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_roam(padapter)) {
- psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
- if (psta)
- rtw_free_stainfo(padapter, psta);
- }
- #endif
- report_join_res(padapter, -2, WLAN_STATUS_UNSPECIFIED_FAILURE);
- return;
- }
- #ifdef CONFIG_RTW_80211R
- if (rtw_ft_roam(padapter)) {
- RTW_INFO("link_timer_hdl: reassoc timeout and try again\n");
- issue_reassocreq(padapter);
- } else
- #endif
- {
- RTW_INFO("link_timer_hdl: assoc timeout and try again\n");
- issue_assocreq(padapter);
- }
- set_link_timer(pmlmeext, REASSOC_TO);
- }
- exit:
- return;
- }
- void addba_timer_hdl(void *ctx)
- {
- struct sta_info *psta = (struct sta_info *)ctx;
- #ifdef CONFIG_80211N_HT
- struct ht_priv *phtpriv;
- if (!psta)
- return;
- phtpriv = &psta->htpriv;
- if ((phtpriv->ht_option == _TRUE) && (phtpriv->ampdu_enable == _TRUE)) {
- if (phtpriv->candidate_tid_bitmap)
- phtpriv->candidate_tid_bitmap = 0x0;
- }
- #endif /* CONFIG_80211N_HT */
- }
- #ifdef CONFIG_IEEE80211W
- void report_sta_timeout_event(_adapter *padapter, u8 *MacAddr, unsigned short reason)
- {
- struct cmd_obj *pcmd_obj;
- u8 *pevtcmd;
- u32 cmdsz;
- struct sta_info *psta;
- int mac_id;
- struct stadel_event *pdel_sta_evt;
- struct C2HEvent_Header *pc2h_evt_hdr;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
- return;
- cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- return;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct stadel_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_TimeoutSTA);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- _rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
- _rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
- psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
- if (psta)
- mac_id = (int)psta->cmn.mac_id;
- else
- mac_id = (-1);
- pdel_sta_evt->mac_id = mac_id;
- RTW_INFO("report_del_sta_event: delete STA, mac_id=%d\n", mac_id);
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- return;
- }
- void clnt_sa_query_timeout(_adapter *padapter)
- {
- struct mlme_ext_priv *mlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
- RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
- receive_disconnect(padapter, get_my_bssid(&(mlmeinfo->network)), WLAN_REASON_SA_QUERY_TIMEOUT, _FALSE);
- }
- void sa_query_timer_hdl(void *ctx)
- {
- struct sta_info *psta = (struct sta_info *)ctx;
- _adapter *padapter = psta->padapter;
- _irqL irqL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE &&
- check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
- clnt_sa_query_timeout(padapter);
- else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
- report_sta_timeout_event(padapter, psta->cmn.mac_addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
- }
- #endif /* CONFIG_IEEE80211W */
- #ifdef CONFIG_RTW_80211R
- void rtw_ft_update_bcn(_adapter *padapter, union recv_frame *precv_frame)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 *pframe = precv_frame->u.hdr.rx_data;
- uint len = precv_frame->u.hdr.len;
- WLAN_BSSID_EX *pbss;
- if (rtw_ft_chk_status(padapter,RTW_FT_ASSOCIATED_STA)
- && (pmlmepriv->ft_roam.ft_updated_bcn == _FALSE)) {
- pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));
- if (pbss) {
- if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
- struct beacon_keys recv_beacon;
- update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);
- rtw_get_bcn_info(&(pmlmepriv->cur_network));
-
- /* update bcn keys */
- if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) {
- RTW_INFO("%s: beacon keys ready\n", __func__);
- _rtw_memcpy(&pmlmepriv->cur_beacon_keys,
- &recv_beacon, sizeof(recv_beacon));
- } else {
- RTW_ERR("%s: get beacon keys failed\n", __func__);
- _rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon));
- }
- #ifdef CONFIG_BCN_CNT_CONFIRM_HDL
- pmlmepriv->new_beacon_cnts = 0;
- #endif
- }
- rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
- }
- /* check the vendor of the assoc AP */
- pmlmeinfo->assoc_AP_vendor =
- check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr),
- (len - sizeof(struct rtw_ieee80211_hdr_3addr)));
- /* update TSF Value */
- update_TSF(pmlmeext, pframe, len);
- pmlmeext->bcn_cnt = 0;
- pmlmeext->last_bcn_cnt = 0;
- pmlmepriv->ft_roam.ft_updated_bcn = _TRUE;
- }
- }
- void rtw_ft_start_clnt_join(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
- if (rtw_ft_otd_roam(padapter)) {
- pmlmeinfo->state = WIFI_FW_AUTH_SUCCESS | WIFI_FW_STATION_STATE;
- pft_roam->ft_event.ies =
- (pft_roam->ft_action + sizeof(struct rtw_ieee80211_hdr_3addr) + 16);
- pft_roam->ft_event.ies_len =
- (pft_roam->ft_action_len - sizeof(struct rtw_ieee80211_hdr_3addr));
- /*Not support RIC*/
- pft_roam->ft_event.ric_ies = NULL;
- pft_roam->ft_event.ric_ies_len = 0;
- rtw_ft_report_evt(padapter);
- return;
- }
- pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
- start_clnt_auth(padapter);
- }
- u8 rtw_ft_update_rsnie(
- _adapter *padapter, u8 bwrite,
- struct pkt_attrib *pattrib, u8 **pframe)
- {
- struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
- u8 *pie;
- u32 len;
- pie = rtw_get_ie(pft_roam->updated_ft_ies, EID_WPA2, &len,
- pft_roam->updated_ft_ies_len);
- if (!bwrite)
- return (pie)?_SUCCESS:_FAIL;
-
- if (pie) {
- *pframe = rtw_set_ie(((u8 *)*pframe), EID_WPA2, len,
- pie+2, &(pattrib->pktlen));
- } else
- return _FAIL;
- return _SUCCESS;
- }
- static u8 rtw_ft_update_mdie(
- _adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
- {
- struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
- u8 *pie, mdie[3];
- u32 len = 3;
- if (rtw_ft_roam(padapter)) {
- if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _MDIE_,
- &len, pft_roam->updated_ft_ies_len))) {
- pie = (pie + 2); /* ignore md-id & length */
- } else
- return _FAIL;
- } else {
- *((u16 *)&mdie[0]) = pft_roam->mdid;
- mdie[2] = pft_roam->ft_cap;
- pie = &mdie[0];
- }
- *pframe = rtw_set_ie(((u8 *)*pframe), _MDIE_, len , pie, &(pattrib->pktlen));
- return _SUCCESS;
- }
- static u8 rtw_ft_update_ftie(
- _adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
- {
- struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
- u8 *pie;
- u32 len;
- if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _FTIE_, &len,
- pft_roam->updated_ft_ies_len)) != NULL) {
- *pframe = rtw_set_ie(*pframe, _FTIE_, len ,
- (pie+2), &(pattrib->pktlen));
- } else
- return _FAIL;
- return _SUCCESS;
- }
- void rtw_ft_build_auth_req_ies(_adapter *padapter,
- struct pkt_attrib *pattrib, u8 **pframe)
- {
- u8 ftie_append = _TRUE;
- if (!pattrib || !(*pframe))
- return;
- if (!rtw_ft_roam(padapter))
- return;
- ftie_append = rtw_ft_update_rsnie(padapter, _TRUE, pattrib, pframe);
- rtw_ft_update_mdie(padapter, pattrib, pframe);
- if (ftie_append)
- rtw_ft_update_ftie(padapter, pattrib, pframe);
- }
- void rtw_ft_build_assoc_req_ies(_adapter *padapter,
- u8 is_reassoc, struct pkt_attrib *pattrib, u8 **pframe)
- {
- if (!pattrib || !(*pframe))
- return;
- if (rtw_ft_chk_flags(padapter, RTW_FT_PEER_EN))
- rtw_ft_update_mdie(padapter, pattrib, pframe);
- if ((!is_reassoc) || (!rtw_ft_roam(padapter)))
- return;
- if (rtw_ft_update_rsnie(padapter, _FALSE, pattrib, pframe))
- rtw_ft_update_ftie(padapter, pattrib, pframe);
- }
- u8 rtw_ft_update_auth_rsp_ies(_adapter *padapter, u8 *pframe, u32 len)
- {
- u8 ret = _SUCCESS;
- u8 target_ap_addr[ETH_ALEN] = {0};
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
- if (!rtw_ft_roam(padapter))
- return _FAIL;
- /*rtw_ft_report_reassoc_evt already,
- * and waiting for cfg80211_rtw_update_ft_ies */
- if (rtw_ft_authed_sta(padapter))
- return ret;
- if (!pframe || !len)
- return _FAIL;
-
- rtw_buf_update(&pmlmepriv->auth_rsp,
- &pmlmepriv->auth_rsp_len, pframe, len);
- pft_roam->ft_event.ies =
- (pmlmepriv->auth_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6);
- pft_roam->ft_event.ies_len =
- (pmlmepriv->auth_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6);
- /*Not support RIC*/
- pft_roam->ft_event.ric_ies = NULL;
- pft_roam->ft_event.ric_ies_len = 0;
- _rtw_memcpy(target_ap_addr, pmlmepriv->assoc_bssid, ETH_ALEN);
- rtw_ft_report_reassoc_evt(padapter, target_ap_addr);
- return ret;
- }
- static void rtw_ft_start_clnt_action(_adapter *padapter, u8 *pTargetAddr)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- rtw_ft_set_status(padapter, RTW_FT_REQUESTING_STA);
- rtw_ft_issue_action_req(padapter, pTargetAddr);
- _set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
- }
- void rtw_ft_start_roam(_adapter *padapter, u8 *pTargetAddr)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- if (rtw_ft_otd_roam(padapter)) {
- rtw_ft_start_clnt_action(padapter, pTargetAddr);
- } else {
- /*wait a little time to retrieve packets buffered in the current ap while scan*/
- _set_timer(&pmlmeext->ft_roam_timer, 30);
- }
- }
- void rtw_ft_issue_action_req(_adapter *padapter, u8 *pTargetAddr)
- {
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct xmit_frame *pmgntframe;
- struct rtw_ieee80211_hdr *pwlanhdr;
- struct pkt_attrib *pattrib;
- u8 *pframe;
- u8 category = RTW_WLAN_CATEGORY_FT;
- u8 action = RTW_WLAN_ACTION_FT_REQ;
- pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
- return;
- pattrib = &pmgntframe->attrib;
- update_mgntframe_attrib(padapter, pattrib);
- _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
- pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
- pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
- pwlanhdr->frame_ctl = 0;
- _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
- _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
- pmlmeext->mgnt_seq++;
- set_frame_sub_type(pframe, WIFI_ACTION);
- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
- _rtw_memcpy(pframe, adapter_mac_addr(padapter), ETH_ALEN);
- pframe += ETH_ALEN;
- pattrib->pktlen += ETH_ALEN;
- _rtw_memcpy(pframe, pTargetAddr, ETH_ALEN);
- pframe += ETH_ALEN;
- pattrib->pktlen += ETH_ALEN;
- rtw_ft_update_mdie(padapter, pattrib, &pframe);
- if (rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe))
- rtw_ft_update_ftie(padapter, pattrib, &pframe);
- pattrib->last_txcmdsz = pattrib->pktlen;
- dump_mgntframe(padapter, pmgntframe);
- }
- void rtw_ft_report_evt(_adapter *padapter)
- {
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);
- struct cfg80211_ft_event_params ft_evt_parms;
- _irqL irqL;
- _rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));
- rtw_ft_update_stainfo(padapter, pnetwork);
- if (!pnetwork)
- goto err_2;
- ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;
- ft_evt_parms.ies = rtw_zmalloc(ft_evt_parms.ies_len);
- if (ft_evt_parms.ies)
- _rtw_memcpy((void *)ft_evt_parms.ies, pft_roam->ft_event.ies, ft_evt_parms.ies_len);
- else
- goto err_2;
- ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);
- if (ft_evt_parms.target_ap)
- _rtw_memcpy((void *)ft_evt_parms.target_ap, pnetwork->MacAddress, ETH_ALEN);
- else
- goto err_1;
- ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;
- ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;
- rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA, &irqL);
- rtw_cfg80211_ft_event(padapter, &ft_evt_parms);
- RTW_INFO("FT: rtw_ft_report_evt\n");
- rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);
- err_1:
- rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);
- err_2:
- return;
- }
- void rtw_ft_report_reassoc_evt(_adapter *padapter, u8 *pMacAddr)
- {
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
- struct cmd_obj *pcmd_obj = NULL;
- struct stassoc_event *passoc_sta_evt = NULL;
- struct C2HEvent_Header *pc2h_evt_hdr = NULL;
- u8 *pevtcmd = NULL;
- u32 cmdsz = 0;
- pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
- return;
- cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
- pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
- return;
- }
- _rtw_init_listhead(&pcmd_obj->list);
- pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
- pcmd_obj->cmdsz = cmdsz;
- pcmd_obj->parmbuf = pevtcmd;
- pcmd_obj->rsp = NULL;
- pcmd_obj->rspsz = 0;
- pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
- pc2h_evt_hdr->len = sizeof(struct stassoc_event);
- pc2h_evt_hdr->ID = GEN_EVT_CODE(_FT_REASSOC);
- pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
- passoc_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
- _rtw_memcpy((unsigned char *)(&(passoc_sta_evt->macaddr)), pMacAddr, ETH_ALEN);
- rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
- }
- void rtw_ft_link_timer_hdl(void *ctx)
- {
- _adapter *padapter = (_adapter *)ctx;
- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
- if (rtw_ft_chk_status(padapter, RTW_FT_REQUESTING_STA)) {
- if (pft_roam->ft_req_retry_cnt < RTW_FT_ACTION_REQ_LMT) {
- pft_roam->ft_req_retry_cnt++;
- rtw_ft_issue_action_req(padapter, (u8 *)pmlmepriv->roam_network->network.MacAddress);
- _set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
- } else {
- pft_roam->ft_req_retry_cnt = 0;
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
- rtw_ft_set_status(padapter, RTW_FT_ASSOCIATED_STA);
- else
- rtw_ft_reset_status(padapter);
- }
- }
- }
- void rtw_ft_roam_timer_hdl(void *ctx)
- {
- _adapter *padapter = (_adapter *)ctx;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress
- , WLAN_REASON_ACTIVE_ROAM, _FALSE);
- }
- void rtw_ft_roam_status_reset(_adapter *padapter)
- {
- struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
- if ((rtw_to_roam(padapter) > 0) &&
- (!rtw_ft_chk_status(padapter, RTW_FT_REQUESTED_STA))) {
- rtw_ft_reset_status(padapter);
- }
-
- padapter->mlmepriv.ft_roam.ft_updated_bcn = _FALSE;
- }
- #endif
- u8 NULL_hdl(_adapter *padapter, u8 *pbuf)
- {
- return H2C_SUCCESS;
- }
- #ifdef CONFIG_AUTO_AP_MODE
- void rtw_auto_ap_rx_msg_dump(_adapter *padapter, union recv_frame *precv_frame, u8 *ehdr_pos)
- {
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct sta_info *psta = precv_frame->u.hdr.psta;
- struct ethhdr *ehdr = (struct ethhdr *)ehdr_pos;
- RTW_INFO("eth rx: got eth_type=0x%x\n", ntohs(ehdr->h_proto));
- if (psta && psta->isrc && psta->pid > 0) {
- u16 rx_pid;
- rx_pid = *(u16 *)(ehdr_pos + ETH_HLEN);
- RTW_INFO("eth rx(pid=0x%x): sta("MAC_FMT") pid=0x%x\n",
- rx_pid, MAC_ARG(psta->cmn.mac_addr), psta->pid);
- if (rx_pid == psta->pid) {
- int i;
- u16 len = *(u16 *)(ehdr_pos + ETH_HLEN + 2);
- /* u16 ctrl_type = *(u16 *)(ehdr_pos + ETH_HLEN + 4); */
- /* RTW_INFO("eth, RC: len=0x%x, ctrl_type=0x%x\n", len, ctrl_type); */
- RTW_INFO("eth, RC: len=0x%x\n", len);
- for (i = 0; i < len; i++)
- RTW_INFO("0x%x\n", *(ehdr_pos + ETH_HLEN + 4 + i));
- /* RTW_INFO("0x%x\n", *(ehdr_pos + ETH_HLEN + 6 + i)); */
- RTW_INFO("eth, RC-end\n");
- }
- }
- }
- void rtw_start_auto_ap(_adapter *adapter)
- {
- RTW_INFO("%s\n", __FUNCTION__);
- rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11APMode);
- rtw_setopmode_cmd(adapter, Ndis802_11APMode, RTW_CMDF_WAIT_ACK);
- }
- static int rtw_auto_ap_start_beacon(_adapter *adapter)
- {
- int ret = 0;
- u8 *pbuf = NULL;
- uint len;
- u8 supportRate[16];
- int sz = 0, rateLen;
- u8 *ie;
- u8 wireless_mode, oper_channel;
- u8 ssid[3] = {0}; /* hidden ssid */
- u32 ssid_len = sizeof(ssid);
- struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
- return -EINVAL;
- len = 128;
- pbuf = rtw_zmalloc(len);
- if (!pbuf)
- return -ENOMEM;
- /* generate beacon */
- ie = pbuf;
- /* timestamp will be inserted by hardware */
- sz += 8;
- ie += sz;
- /* beacon interval : 2bytes */
- *(u16 *)ie = cpu_to_le16((u16)100); /* BCN_INTERVAL=100; */
- sz += 2;
- ie += 2;
- /* capability info */
- *(u16 *)ie = 0;
- *(u16 *)ie |= cpu_to_le16(cap_ESS);
- *(u16 *)ie |= cpu_to_le16(cap_ShortPremble);
- /* *(u16*)ie |= cpu_to_le16(cap_Privacy); */
- sz += 2;
- ie += 2;
- /* SSID */
- ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);
- /* supported rates */
- wireless_mode = WIRELESS_11BG_24N;
- rtw_set_supported_rate(supportRate, wireless_mode) ;
- rateLen = rtw_get_rateset_len(supportRate);
- if (rateLen > 8)
- ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);
- else
- ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);
- /* DS parameter set */
- if (rtw_mi_check_status(adapter, MI_LINKED))
- oper_channel = rtw_mi_get_union_chan(adapter);
- else
- oper_channel = adapter_to_dvobj(adapter)->oper_channel;
- ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);
- /* ext supported rates */
- if (rateLen > 8)
- ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);
- RTW_INFO("%s, start auto ap beacon sz=%d\n", __FUNCTION__, sz);
- /* lunch ap mode & start to issue beacon */
- if (rtw_check_beacon_data(adapter, pbuf, sz) == _SUCCESS) {
- } else
- ret = -EINVAL;
- rtw_mfree(pbuf, len);
- return ret;
- }
- #endif/* CONFIG_AUTO_AP_MODE */
- u8 setopmode_hdl(_adapter *padapter, u8 *pbuf)
- {
- u8 type;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
- if (psetop->mode == Ndis802_11APMode
- || psetop->mode == Ndis802_11_mesh
- ) {
- pmlmeinfo->state = WIFI_FW_AP_STATE;
- type = _HW_STATE_AP_;
- } else if (psetop->mode == Ndis802_11Infrastructure) {
- pmlmeinfo->state &= ~(BIT(0) | BIT(1)); /* clear state */
- pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
- type = _HW_STATE_STATION_;
- } else if (psetop->mode == Ndis802_11IBSS)
- type = _HW_STATE_ADHOC_;
- else if (psetop->mode == Ndis802_11Monitor)
- type = _HW_STATE_MONITOR_;
- else
- type = _HW_STATE_NOLINK_;
- #ifdef CONFIG_AP_PORT_SWAP
- rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, (u8 *)(&type));
- #endif
- rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
- #ifdef CONFIG_AUTO_AP_MODE
- if (psetop->mode == Ndis802_11APMode)
- rtw_auto_ap_start_beacon(padapter);
- #endif
- if (rtw_port_switch_chk(padapter) == _TRUE) {
- rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
- if (psetop->mode == Ndis802_11APMode)
- adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; /* ap mode won't dowload rsvd pages */
- else if (psetop->mode == Ndis802_11Infrastructure) {
- #ifdef CONFIG_LPS
- _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
- if (port0_iface)
- rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
- #endif
- }
- }
- #ifdef CONFIG_BT_COEXIST
- if (psetop->mode == Ndis802_11APMode
- || psetop->mode == Ndis802_11_mesh
- || psetop->mode == Ndis802_11Monitor
- ) {
- /* Do this after port switch to */
- /* prevent from downloading rsvd page to wrong port */
- rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */
- }
- #endif /* CONFIG_BT_COEXIST */
- return H2C_SUCCESS;
- }
- u8 createbss_hdl(_adapter *padapter, u8 *pbuf)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
- WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
- struct createbss_parm *parm = (struct createbss_parm *)pbuf;
- u8 ret = H2C_SUCCESS;
- /* u8 initialgain; */
- #ifdef CONFIG_AP_MODE
- if ((parm->req_ch == 0 && pmlmeinfo->state == WIFI_FW_AP_STATE)
- || parm->req_ch != 0
- ) {
- start_bss_network(padapter, parm);
- goto exit;
- }
- #endif
- /* below is for ad-hoc master */
- if (parm->adhoc) {
- rtw_warn_on(pdev_network->InfrastructureMode != Ndis802_11IBSS);
- rtw_joinbss_reset(padapter);
- pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
- pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- pmlmeinfo->ERP_enable = 0;
- pmlmeinfo->WMM_enable = 0;
- pmlmeinfo->HT_enable = 0;
- pmlmeinfo->HT_caps_enable = 0;
- pmlmeinfo->HT_info_enable = 0;
- pmlmeinfo->agg_enable_bitmap = 0;
- pmlmeinfo->candidate_tid_bitmap = 0;
- /* cancel link timer */
- _cancel_timer_ex(&pmlmeext->link_timer);
- /* clear CAM */
- flush_all_cam_entry(padapter);
- pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
- _rtw_memcpy(pnetwork, pdev_network, FIELD_OFFSET(WLAN_BSSID_EX, IELength));
- pnetwork->IELength = pdev_network->IELength;
- if (pnetwork->IELength > MAX_IE_SZ) {
- ret = H2C_PARAMETERS_ERROR;
- goto ibss_post_hdl;
- }
- _rtw_memcpy(pnetwork->IEs, pdev_network->IEs, pnetwork->IELength);
- start_create_ibss(padapter);
- } else {
- rtw_warn_on(1);
- ret = H2C_PARAMETERS_ERROR;
- }
- ibss_post_hdl:
- rtw_create_ibss_post_hdl(padapter, ret);
- exit:
- return ret;
- }
- u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf)
- {
- u8 join_type;
- PNDIS_802_11_VARIABLE_IEs pIE;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
- #ifdef CONFIG_ANTENNA_DIVERSITY
- struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
- #endif /* CONFIG_ANTENNA_DIVERSITY */
- u32 i;
- /* u8 initialgain; */
- /* u32 acparm; */
- u8 u_ch, u_bw, u_offset;
- u8 doiqk = _FALSE;
- /* check already connecting to AP or not */
- if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
- if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
- pmlmeinfo->state = WIFI_FW_NULL_STATE;
- /* clear CAM */
- flush_all_cam_entry(padapter);
- _cancel_timer_ex(&pmlmeext->link_timer);
- /* set MSR to nolink->infra. mode */
- /* Set_MSR(padapter, _HW_STATE_NOLINK_); */
- Set_MSR(padapter, _HW_STATE_STATION_);
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
- if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_DISCONNECTED);
- }
- #ifdef CONFIG_ANTENNA_DIVERSITY
- rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, _FALSE);
- #endif
- #ifdef CONFIG_WAPI_SUPPORT
- rtw_wapi_clear_all_cam_entry(padapter);
- #endif
- rtw_joinbss_reset(padapter);
- pmlmeinfo->ERP_enable = 0;
- pmlmeinfo->WMM_enable = 0;
- pmlmeinfo->HT_enable = 0;
- pmlmeinfo->HT_caps_enable = 0;
- pmlmeinfo->HT_info_enable = 0;
- pmlmeinfo->agg_enable_bitmap = 0;
- pmlmeinfo->candidate_tid_bitmap = 0;
- pmlmeinfo->bwmode_updated = _FALSE;
- /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
- pmlmeinfo->VHT_enable = 0;
- #ifdef ROKU_PRIVATE
- pmlmeinfo->ht_vht_received = 0;
- _rtw_memset(pmlmeinfo->SupportedRates_infra_ap, 0, NDIS_802_11_LENGTH_RATES_EX);
- #endif /* ROKU_PRIVATE */
- _rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength));
- pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
- if (pnetwork->IELength > MAX_IE_SZ) /* Check pbuf->IELength */
- return H2C_PARAMETERS_ERROR;
- if (pnetwork->IELength < 2) {
- report_join_res(padapter, (-4), WLAN_STATUS_UNSPECIFIED_FAILURE);
- return H2C_SUCCESS;
- }
- _rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength);
- pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
- /* Check AP vendor to move rtw_joinbss_cmd() */
- /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */
- /* sizeof(NDIS_802_11_FIXED_IEs) */
- for (i = _FIXED_IE_LENGTH_ ; i < pnetwork->IELength - 2 ;) {
- pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
- switch (pIE->ElementID) {
- case _VENDOR_SPECIFIC_IE_: /* Get WMM IE. */
- if (_rtw_memcmp(pIE->data, WMM_OUI, 4))
- WMM_param_handler(padapter, pIE);
- break;
- #ifdef CONFIG_80211N_HT
- case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */
- pmlmeinfo->HT_caps_enable = 1;
- break;
- case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */
- pmlmeinfo->HT_info_enable = 1;
- break;
- #endif /* CONFIG_80211N_HT */
- #ifdef CONFIG_80211AC_VHT
- case EID_VHTCapability: /* Get VHT Cap IE. */
- pmlmeinfo->VHT_enable = 1;
- break;
- case EID_VHTOperation: /* Get VHT Operation IE. */
- break;
- #endif /* CONFIG_80211AC_VHT */
- default:
- break;
- }
- i += (pIE->Length + 2);
- }
- rtw_bss_get_chbw(pnetwork
- , &pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset, 1, 1);
- rtw_adjust_chbw(padapter, pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset);
- #if 0
- if (padapter->registrypriv.wifi_spec) {
- /* for WiFi test, follow WMM test plan spec */
- acparm = 0x002F431C; /* VO */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
- acparm = 0x005E541C; /* VI */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
- acparm = 0x0000A525; /* BE */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
- acparm = 0x0000A549; /* BK */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
- /* for WiFi test, mixed mode with intel STA under bg mode throughput issue */
- if (padapter->mlmepriv.htpriv.ht_option == _FALSE) {
- acparm = 0x00004320;
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
- }
- } else {
- acparm = 0x002F3217; /* VO */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
- acparm = 0x005E4317; /* VI */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
- acparm = 0x00105320; /* BE */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
- acparm = 0x0000A444; /* BK */
- rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
- }
- #endif
- /* check channel, bandwidth, offset and switch */
- if (rtw_chk_start_clnt_join(padapter, &u_ch, &u_bw, &u_offset) == _FAIL) {
- report_join_res(padapter, (-4), WLAN_STATUS_UNSPECIFIED_FAILURE);
- return H2C_SUCCESS;
- }
- /* disable dynamic functions, such as high power, DIG */
- /*rtw_phydm_func_disable_all(padapter);*/
- /* config the initial gain under linking, need to write the BB registers */
- /* initialgain = 0x1E; */
- /*rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);*/
- rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
- if (MLME_IS_STA(padapter))
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_CONNECTING);
- else
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_ADHOC_STARTED);
- join_type = 0;
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
- doiqk = _TRUE;
- rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
- set_channel_bwmode(padapter, u_ch, u_offset, u_bw);
- rtw_mi_update_union_chan_inf(padapter, u_ch, u_offset, u_bw);
- doiqk = _FALSE;
- rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
- /* cancel link timer */
- _cancel_timer_ex(&pmlmeext->link_timer);
- start_clnt_join(padapter);
- return H2C_SUCCESS;
- }
- u8 disconnect_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- #ifdef CONFIG_DFS
- struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
- #endif
- struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));
- u8 val8;
- if (is_client_associated_to_ap(padapter)
- #ifdef CONFIG_DFS
- && !IS_RADAR_DETECTED(rfctl) && !rfctl->csa_ch
- #endif
- ) {
- #ifdef CONFIG_PLATFORM_ROCKCHIPS
- /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
- #else
- issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100);
- #endif /* CONFIG_PLATFORM_ROCKCHIPS */
- }
- #ifndef CONFIG_SUPPORT_MULTI_BCN
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
- /* Stop BCN */
- val8 = 0;
- rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
- }
- #endif
- rtw_mlmeext_disconnect(padapter);
- rtw_free_uc_swdec_pending_queue(padapter);
- rtw_sta_mstatus_report(padapter);
- return H2C_SUCCESS;
- }
- static const char *const _scan_state_str[] = {
- "SCAN_DISABLE",
- "SCAN_START",
- "SCAN_PS_ANNC_WAIT",
- "SCAN_ENTER",
- "SCAN_PROCESS",
- "SCAN_BACKING_OP",
- "SCAN_BACK_OP",
- "SCAN_LEAVING_OP",
- "SCAN_LEAVE_OP",
- "SCAN_SW_ANTDIV_BL",
- "SCAN_TO_P2P_LISTEN",
- "SCAN_P2P_LISTEN",
- "SCAN_COMPLETE",
- "SCAN_STATE_MAX",
- };
- const char *scan_state_str(u8 state)
- {
- state = (state >= SCAN_STATE_MAX) ? SCAN_STATE_MAX : state;
- return _scan_state_str[state];
- }
- static bool scan_abort_hdl(_adapter *adapter)
- {
- struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
- struct ss_res *ss = &pmlmeext->sitesurvey_res;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &adapter->wdinfo;
- #endif
- bool ret = _FALSE;
- if (pmlmeext->scan_abort == _TRUE) {
- #ifdef CONFIG_P2P
- if (!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE)) {
- rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
- ss->channel_idx = 3;
- RTW_INFO("%s idx:%d, cnt:%u\n", __FUNCTION__
- , ss->channel_idx
- , pwdinfo->find_phase_state_exchange_cnt
- );
- } else
- #endif
- {
- ss->channel_idx = ss->ch_num;
- RTW_INFO("%s idx:%d\n", __FUNCTION__
- , ss->channel_idx
- );
- }
- pmlmeext->scan_abort = _FALSE;
- ret = _TRUE;
- }
- return ret;
- }
- u8 rtw_scan_sparse(_adapter *adapter, struct rtw_ieee80211_channel *ch, u8 ch_num)
- {
- /* interval larger than this is treated as backgroud scan */
- #ifndef RTW_SCAN_SPARSE_BG_INTERVAL_MS
- #define RTW_SCAN_SPARSE_BG_INTERVAL_MS 12000
- #endif
- #ifndef RTW_SCAN_SPARSE_CH_NUM_MIRACAST
- #define RTW_SCAN_SPARSE_CH_NUM_MIRACAST 1
- #endif
- #ifndef RTW_SCAN_SPARSE_CH_NUM_BG
- #define RTW_SCAN_SPARSE_CH_NUM_BG 4
- #endif
- #ifdef CONFIG_LAYER2_ROAMING
- #ifndef RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE
- #define RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE 1
- #endif
- #endif
- #define SCAN_SPARSE_CH_NUM_INVALID 255
- static u8 token = 255;
- u32 interval;
- bool busy_traffic = _FALSE;
- bool miracast_enabled = _FALSE;
- bool bg_scan = _FALSE;
- u8 max_allow_ch = SCAN_SPARSE_CH_NUM_INVALID;
- u8 scan_division_num;
- u8 ret_num = ch_num;
- struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- if (regsty->wifi_spec)
- goto exit;
- /* assume ch_num > 6 is normal scan */
- if (ch_num <= 6)
- goto exit;
- if (mlmeext->last_scan_time == 0)
- mlmeext->last_scan_time = rtw_get_current_time();
- interval = rtw_get_passing_time_ms(mlmeext->last_scan_time);
- if (rtw_mi_busy_traffic_check(adapter, _FALSE))
- busy_traffic = _TRUE;
- if (rtw_mi_check_miracast_enabled(adapter))
- miracast_enabled = _TRUE;
- if (interval > RTW_SCAN_SPARSE_BG_INTERVAL_MS)
- bg_scan = _TRUE;
- /* max_allow_ch by conditions*/
- #if RTW_SCAN_SPARSE_MIRACAST
- if (miracast_enabled == _TRUE && busy_traffic == _TRUE)
- max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_MIRACAST);
- #endif
- #if RTW_SCAN_SPARSE_BG
- if (bg_scan == _TRUE)
- max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_BG);
- #endif
- #if defined(CONFIG_LAYER2_ROAMING) && defined(RTW_SCAN_SPARSE_ROAMING_ACTIVE)
- if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
- if (busy_traffic == _TRUE && adapter->mlmepriv.need_to_roam == _TRUE)
- max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE);
- }
- #endif
- if (max_allow_ch != SCAN_SPARSE_CH_NUM_INVALID) {
- int i;
- int k = 0;
- scan_division_num = (ch_num / max_allow_ch) + ((ch_num % max_allow_ch) ? 1 : 0);
- token = (token + 1) % scan_division_num;
- if (0)
- RTW_INFO("scan_division_num:%u, token:%u\n", scan_division_num, token);
- for (i = 0; i < ch_num; i++) {
- if (ch[i].hw_value && (i % scan_division_num) == token
- ) {
- if (i != k)
- _rtw_memcpy(&ch[k], &ch[i], sizeof(struct rtw_ieee80211_channel));
- k++;
- }
- }
- _rtw_memset(&ch[k], 0, sizeof(struct rtw_ieee80211_channel));
- ret_num = k;
- mlmeext->last_scan_time = rtw_get_current_time();
- }
- exit:
- return ret_num;
- }
- #ifdef CONFIG_SCAN_BACKOP
- u8 rtw_scan_backop_decision(_adapter *adapter)
- {
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- struct mi_state mstate;
- u8 backop_flags = 0;
- rtw_mi_status(adapter, &mstate);
- if ((MSTATE_STA_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN))
- || (MSTATE_STA_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN_NL)))
- backop_flags |= mlmeext_scan_backop_flags_sta(mlmeext);
- #ifdef CONFIG_AP_MODE
- if ((MSTATE_AP_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN))
- || (MSTATE_AP_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN_NL)))
- backop_flags |= mlmeext_scan_backop_flags_ap(mlmeext);
- #endif
- #ifdef CONFIG_RTW_MESH
- if ((MSTATE_MESH_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN))
- || (MSTATE_MESH_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN_NL)))
- backop_flags |= mlmeext_scan_backop_flags_mesh(mlmeext);
- #endif
- return backop_flags;
- }
- #endif
- #define SCANNING_TIMEOUT_EX 2000
- u32 rtw_scan_timeout_decision(_adapter *padapter)
- {
- u32 back_op_times= 0;
- u8 max_chan_num;
- u16 scan_ms;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct ss_res *ss = &pmlmeext->sitesurvey_res;
- if (is_supported_5g(padapter->registrypriv.wireless_mode)
- && IsSupported24G(padapter->registrypriv.wireless_mode))
- max_chan_num = MAX_CHANNEL_NUM;/* dual band */
- else
- max_chan_num = MAX_CHANNEL_NUM_2G;/*single band*/
- #ifdef CONFIG_SCAN_BACKOP
- if (rtw_scan_backop_decision(padapter))
- back_op_times = (max_chan_num / ss->scan_cnt_max) * ss->backop_ms;
- #endif
- if (ss->duration)
- scan_ms = ss->duration;
- else
- #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
- if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter))
- scan_ms = rtw_acs_get_adv_st(padapter);
- else
- #endif /*CONFIG_RTW_ACS*/
- scan_ms = ss->scan_ch_ms;
- ss->scan_timeout_ms = (scan_ms * max_chan_num) + back_op_times + SCANNING_TIMEOUT_EX;
- #ifdef DBG_SITESURVEY
- RTW_INFO("%s , scan_timeout_ms = %d (ms)\n", __func__, ss->scan_timeout_ms);
- #endif /*DBG_SITESURVEY*/
- return ss->scan_timeout_ms;
- }
- static int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out,
- u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
- {
- int i, j;
- int set_idx;
- u8 chan;
- struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
- /* clear first */
- _rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num);
- /* acquire channels from in */
- j = 0;
- for (i = 0; i < in_num; i++) {
- if (0)
- RTW_INFO(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
- if (!in[i].hw_value || (in[i].flags & RTW_IEEE80211_CHAN_DISABLED))
- continue;
- if (rtw_mlme_band_check(padapter, in[i].hw_value) == _FALSE)
- continue;
- set_idx = rtw_chset_search_ch(rfctl->channel_set, in[i].hw_value);
- if (set_idx >= 0) {
- if (j >= out_num) {
- RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n",
- FUNC_ADPT_ARG(padapter), out_num);
- break;
- }
- _rtw_memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
- if (rfctl->channel_set[set_idx].ScanType == SCAN_PASSIVE)
- out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
- j++;
- }
- if (j >= out_num)
- break;
- }
- /* if out is empty, use channel_set as default */
- if (j == 0) {
- for (i = 0; i < rfctl->max_chan_nums; i++) {
- chan = rfctl->channel_set[i].ChannelNum;
- if (rtw_mlme_band_check(padapter, chan) == _TRUE) {
- if (rtw_mlme_ignore_chan(padapter, chan) == _TRUE)
- continue;
- if (0)
- RTW_INFO(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), chan);
- if (j >= out_num) {
- RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n",
- FUNC_ADPT_ARG(padapter), out_num);
- break;
- }
- out[j].hw_value = chan;
- if (rfctl->channel_set[i].ScanType == SCAN_PASSIVE)
- out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
- j++;
- }
- }
- }
- /* scan_sparse */
- j = rtw_scan_sparse(padapter, out, j);
- return j;
- }
- static void sitesurvey_res_reset(_adapter *adapter, struct sitesurvey_parm *parm)
- {
- struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res;
- RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);
- int i;
- ss->bss_cnt = 0;
- ss->channel_idx = 0;
- #ifdef CONFIG_DFS
- ss->dfs_ch_ssid_scan = 0;
- #endif
- ss->igi_scan = 0;
- ss->igi_before_scan = 0;
- #ifdef CONFIG_SCAN_BACKOP
- ss->scan_cnt = 0;
- #endif
- #if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
- ss->is_sw_antdiv_bl_scan = 0;
- #endif
- ss->ssid_num = 0;
- for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (parm->ssid[i].SsidLength) {
- _rtw_memcpy(ss->ssid[i].Ssid, parm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
- ss->ssid[i].SsidLength = parm->ssid[i].SsidLength;
- ss->ssid_num++;
- } else
- ss->ssid[i].SsidLength = 0;
- }
- ss->ch_num = rtw_scan_ch_decision(adapter
- , ss->ch, RTW_CHANNEL_SCAN_AMOUNT
- , parm->ch, parm->ch_num
- );
- #ifdef CONFIG_DFS
- for (i = 0; i < MAX_CHANNEL_NUM; i++)
- chset[i].hidden_bss_cnt = 0;
- #endif
- ss->bw = parm->bw;
- ss->igi = parm->igi;
- ss->token = parm->token;
- ss->duration = parm->duration;
- ss->scan_mode = parm->scan_mode;
- ss->token = parm->token;
- }
- static u8 sitesurvey_pick_ch_behavior(_adapter *padapter, u8 *ch, RT_SCAN_TYPE *type)
- {
- u8 next_state;
- u8 scan_ch = 0;
- RT_SCAN_TYPE scan_type = SCAN_PASSIVE;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct ss_res *ss = &pmlmeext->sitesurvey_res;
- struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
- int ch_set_idx;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &padapter->wdinfo;
- #endif
- #ifdef CONFIG_SCAN_BACKOP
- u8 backop_flags = 0;
- #endif
- /* handle scan abort request */
- scan_abort_hdl(padapter);
- #ifdef CONFIG_P2P
- if (pwdinfo->rx_invitereq_info.scan_op_ch_only || pwdinfo->p2p_info.scan_op_ch_only) {
- if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
- scan_ch = pwdinfo->rx_invitereq_info.operation_ch[ss->channel_idx];
- else
- scan_ch = pwdinfo->p2p_info.operation_ch[ss->channel_idx];
- scan_type = SCAN_ACTIVE;
- } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
- /*
- * Commented by Albert 2011/06/03
- * The driver is in the find phase, it should go through the social channel.
- */
- scan_ch = pwdinfo->social_chan[ss->channel_idx];
- ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, scan_ch);
- if (ch_set_idx >= 0)
- scan_type = rfctl->channel_set[ch_set_idx].ScanType;
- else
- scan_type = SCAN_ACTIVE;
- } else
- #endif /* CONFIG_P2P */
- {
- struct rtw_ieee80211_channel *ch;
- #ifdef CONFIG_SCAN_BACKOP
- backop_flags = rtw_scan_backop_decision(padapter);
- #endif
- #ifdef CONFIG_DFS
- #ifdef CONFIG_SCAN_BACKOP
- if (!(backop_flags && ss->scan_cnt >= ss->scan_cnt_max))
- #endif
- {
- #ifdef CONFIG_RTW_WIFI_HAL
- if (adapter_to_dvobj(padapter)->nodfs) {
- while ( ss->channel_idx < ss->ch_num && rtw_is_dfs_ch(ss->ch[ss->channel_idx].hw_value))
- ss->channel_idx++;
- } else
- #endif
- if (ss->channel_idx != 0 && ss->dfs_ch_ssid_scan == 0
- && pmlmeext->sitesurvey_res.ssid_num
- && rtw_is_dfs_ch(ss->ch[ss->channel_idx - 1].hw_value)
- ) {
- ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, ss->ch[ss->channel_idx - 1].hw_value);
- if (ch_set_idx != -1 && rfctl->channel_set[ch_set_idx].hidden_bss_cnt
- && (!IS_DFS_SLAVE_WITH_RD(rfctl)
- || rtw_odm_dfs_domain_unknown(rfctl_to_dvobj(rfctl))
- || !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx]))
- ) {
- ss->channel_idx--;
- ss->dfs_ch_ssid_scan = 1;
- }
- } else
- ss->dfs_ch_ssid_scan = 0;
- }
- #endif /* CONFIG_DFS */
- if (ss->channel_idx < ss->ch_num) {
- ch = &ss->ch[ss->channel_idx];
- scan_ch = ch->hw_value;
- #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
- if (IS_ACS_ENABLE(padapter) && rtw_is_acs_passiv_scan(padapter))
- scan_type = SCAN_PASSIVE;
- else
- #endif /*CONFIG_RTW_ACS*/
- scan_type = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
- }
- }
- if (scan_ch != 0) {
- next_state = SCAN_PROCESS;
- #ifdef CONFIG_SCAN_BACKOP
- if (backop_flags) {
- if (ss->scan_cnt < ss->scan_cnt_max)
- ss->scan_cnt++;
- else {
- mlmeext_assign_scan_backop_flags(pmlmeext, backop_flags);
- next_state = SCAN_BACKING_OP;
- }
- }
- #endif
- } else if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
- /* go p2p listen */
- next_state = SCAN_TO_P2P_LISTEN;
- #ifdef CONFIG_ANTENNA_DIVERSITY
- } else if (rtw_hal_antdiv_before_linked(padapter)) {
- /* go sw antdiv before link */
- next_state = SCAN_SW_ANTDIV_BL;
- #endif
- } else {
- next_state = SCAN_COMPLETE;
- #if defined(DBG_SCAN_SW_ANTDIV_BL)
- {
- /* for SCAN_SW_ANTDIV_BL state testing */
- struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
- int i;
- bool is_linked = _FALSE;
- for (i = 0; i < dvobj->iface_nums; i++) {
- if (rtw_linked_check(dvobj->padapters[i]))
- is_linked = _TRUE;
- }
- if (!is_linked) {
- static bool fake_sw_antdiv_bl_state = 0;
- if (fake_sw_antdiv_bl_state == 0) {
- next_state = SCAN_SW_ANTDIV_BL;
- fake_sw_antdiv_bl_state = 1;
- } else
- fake_sw_antdiv_bl_state = 0;
- }
- }
- #endif /* defined(DBG_SCAN_SW_ANTDIV_BL) */
- }
- #ifdef CONFIG_SCAN_BACKOP
- if (next_state != SCAN_PROCESS)
- ss->scan_cnt = 0;
- #endif
- #ifdef DBG_FIXED_CHAN
- if (pmlmeext->fixed_chan != 0xff && next_state == SCAN_PROCESS)
- scan_ch = pmlmeext->fixed_chan;
- #endif
- if (ch)
- *ch = scan_ch;
- if (type)
- *type = scan_type;
- return next_state;
- }
- void site_survey(_adapter *padapter, u8 survey_channel, RT_SCAN_TYPE ScanType)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct ss_res *ss = &pmlmeext->sitesurvey_res;
- u8 ssid_scan = 0;
- #ifdef CONFIG_P2P
- #ifndef CONFIG_IOCTL_CFG80211
- struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- #endif
- #endif
- if (survey_channel != 0) {
- set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
- #ifdef CONFIG_DFS
- if (ScanType == SCAN_PASSIVE && ss->dfs_ch_ssid_scan)
- ssid_scan = 1;
- else
- #endif
- if (ScanType == SCAN_ACTIVE) {
- #ifdef CONFIG_P2P
- #ifdef CONFIG_IOCTL_CFG80211
- if (rtw_cfg80211_is_p2p_scan(padapter))
- #else
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
- || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
- #endif
- {
- issue_probereq_p2p(padapter, NULL);
- issue_probereq_p2p(padapter, NULL);
- issue_probereq_p2p(padapter, NULL);
- } else
- #endif /* CONFIG_P2P */
- {
- if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
- /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
- if (padapter->registrypriv.wifi_spec)
- issue_probereq(padapter, NULL, NULL);
- else
- issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
- issue_probereq(padapter, NULL, NULL);
- }
- ssid_scan = 1;
- }
- }
- if (ssid_scan) {
- int i;
- for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
- if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
- /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
- if (padapter->registrypriv.wifi_spec)
- issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
- else
- issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
- issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
- }
- }
- }
- } else {
- /* channel number is 0 or this channel is not valid. */
- rtw_warn_on(1);
- }
- return;
- }
- void survey_done_set_ch_bw(_adapter *padapter)
- {
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- u8 cur_channel = 0;
- u8 cur_bwmode;
- u8 cur_ch_offset;
- #ifdef CONFIG_MCC_MODE
- if (!rtw_hal_mcc_change_scan_flag(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset)) {
- if (0)
- RTW_INFO(FUNC_ADPT_FMT" back to AP channel - ch:%u, bw:%u, offset:%u\n",
- FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
- goto exit;
- }
- #endif
- if (rtw_mi_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0) {
- if (0)
- RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
- FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
- } else {
- #ifdef CONFIG_P2P
- struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
- _adapter *iface;
- int i;
- for (i = 0; i < dvobj->iface_nums; i++) {
- iface = dvobj->padapters[i];
- if (!iface)
- continue;
- #ifdef CONFIG_IOCTL_CFG80211
- if (iface->wdinfo.driver_interface == DRIVER_CFG80211 && !adapter_wdev_data(iface)->p2p_enabled)
- continue;
- #endif
- if (rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_LISTEN)) {
- cur_channel = iface->wdinfo.listen_channel;
- cur_bwmode = CHANNEL_WIDTH_20;
- cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
- if (0)
- RTW_INFO(FUNC_ADPT_FMT" back to "ADPT_FMT"'s listen ch - ch:%u, bw:%u, offset:%u\n",
- FUNC_ADPT_ARG(padapter), ADPT_ARG(iface), cur_channel, cur_bwmode, cur_ch_offset);
- break;
- }
- }
- #endif /* CONFIG_P2P */
- if (cur_channel == 0) {
- cur_channel = pmlmeext->cur_channel;
- cur_bwmode = pmlmeext->cur_bwmode;
- cur_ch_offset = pmlmeext->cur_ch_offset;
- if (0)
- RTW_INFO(FUNC_ADPT_FMT" back to ch:%u, bw:%u, offset:%u\n",
- FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
- }
- }
- #ifdef CONFIG_MCC_MODE
- exit:
- #endif
- set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
- }
- /**
- * rtw_ps_annc - check and doing ps announcement for all the adapters
- * @adapter: the requesting adapter
- * @ps: power saving or not
- *
- * Returns: 0: no ps announcement is doing. 1: ps announcement is doing
- */
- u8 rtw_ps_annc(_adapter *adapter, bool ps)
- {
- struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
- _adapter *iface;
- int i;
- u8 ps_anc = 0;
- for (i = 0; i < dvobj->iface_nums; i++) {
- iface = dvobj->padapters[i];
- if (!iface)
- continue;
- if (MLME_IS_STA(iface)) {
- if (is_client_associated_to_ap(iface) == _TRUE) {
- /* TODO: TDLS peers */
- #ifdef CONFIG_MCC_MODE
- /* for two station case */
- if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_NEED_MCC)) {
- u8 ch = iface->mlmeextpriv.cur_channel;
- u8 offset = iface->mlmeextpriv.cur_ch_offset;
- u8 bw = iface->mlmeextpriv.cur_bwmode;
- set_channel_bwmode(iface, ch, offset, bw);
- }
- #endif /* CONFIG_MCC_MODE */
- issue_nulldata(iface, NULL, ps, 3, 500);
- ps_anc = 1;
- }
- #ifdef CONFIG_RTW_MESH
- } else if (MLME_IS_MESH(iface)) {
- if (rtw_mesh_ps_annc(iface, ps))
- ps_anc = 1;
- #endif
- }
- }
- return ps_anc;
- }
- void rtw_leave_opch(_adapter *adapter)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- #ifdef CONFIG_MCC_MODE
- if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC))
- return;
- #endif
- _enter_critical_mutex(&rfctl->offch_mutex, NULL);
- if (rfctl->offch_state == OFFCHS_NONE) {
- /* prepare to leave operating channel */
- rfctl->offch_state = OFFCHS_LEAVING_OP;
- /* clear HW TX queue */
- rtw_hal_set_hwreg(adapter, HW_VAR_CHECK_TXBUF, 0);
- rtw_hal_macid_sleep_all_used(adapter);
- rtw_ps_annc(adapter, 1);
- rfctl->offch_state = OFFCHS_LEAVE_OP;
- }
- _exit_critical_mutex(&rfctl->offch_mutex, NULL);
- }
- void rtw_back_opch(_adapter *adapter)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- #ifdef CONFIG_MCC_MODE
- if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC))
- return;
- #endif
- _enter_critical_mutex(&rfctl->offch_mutex, NULL);
- if (rfctl->offch_state != OFFCHS_NONE) {
- rfctl->offch_state = OFFCHS_BACKING_OP;
- rtw_hal_macid_wakeup_all_used(adapter);
- rtw_ps_annc(adapter, 0);
- rfctl->offch_state = OFFCHS_NONE;
- rtw_mi_os_xmit_schedule(adapter);
- }
- _exit_critical_mutex(&rfctl->offch_mutex, NULL);
- }
- void sitesurvey_set_igi(_adapter *adapter)
- {
- struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
- struct ss_res *ss = &mlmeext->sitesurvey_res;
- u8 igi;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &adapter->wdinfo;
- #endif
- switch (mlmeext_scan_state(mlmeext)) {
- case SCAN_ENTER:
- #ifdef CONFIG_P2P
- #ifdef CONFIG_IOCTL_CFG80211
- if (pwdinfo->driver_interface == DRIVER_CFG80211 && rtw_cfg80211_is_p2p_scan(adapter))
- igi = 0x30;
- else
- #endif /* CONFIG_IOCTL_CFG80211 */
- if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
- igi = 0x28;
- else
- #endif /* CONFIG_P2P */
- if (ss->igi)
- igi = ss->igi;
- else
- #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
- if (IS_ACS_ENABLE(adapter) && rtw_is_acs_igi_valid(adapter))
- igi = rtw_acs_get_adv_igi(adapter);
- else
- #endif /*CONFIG_RTW_ACS*/
- igi = 0x1e;
- /* record IGI status */
- ss->igi_scan = igi;
- rtw_hal_get_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &ss->igi_before_scan, NULL);
- /* disable DIG and set IGI for scan */
- rtw_hal_set_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &igi, _FALSE);
- break;
- case SCAN_COMPLETE:
- case SCAN_TO_P2P_LISTEN:
- /* enable DIG and restore IGI */
- igi = 0xff;
- rtw_hal_set_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &igi, _FALSE);
- break;
- #ifdef CONFIG_SCAN_BACKOP
- case SCAN_BACKING_OP:
- /* write IGI for op channel when DIG is not enabled */
- odm_write_dig(adapter_to_phydm(adapter), ss->igi_before_scan);
- break;
- case SCAN_LEAVE_OP:
- /* write IGI for scan when DIG is not enabled */
- odm_write_dig(adapter_to_phydm(adapter), ss->igi_scan);
- break;
- #endif /* CONFIG_SCAN_BACKOP */
- default:
- rtw_warn_on(1);
- break;
- }
- }
- void sitesurvey_set_msr(_adapter *adapter, bool enter)
- {
- u8 network_type;
- struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (enter) {
- #ifdef CONFIG_MI_WITH_MBSSID_CAM
- rtw_hal_get_hwreg(adapter, HW_VAR_MEDIA_STATUS, (u8 *)(&pmlmeinfo->hw_media_state));
- #endif
- /* set MSR to no link state */
- network_type = _HW_STATE_NOLINK_;
- } else {
- #ifdef CONFIG_MI_WITH_MBSSID_CAM
- network_type = pmlmeinfo->hw_media_state;
- #else
- network_type = pmlmeinfo->state & 0x3;
- #endif
- }
- Set_MSR(adapter, network_type);
- }
- void sitesurvey_set_offch_state(_adapter *adapter, u8 scan_state)
- {
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- _enter_critical_mutex(&rfctl->offch_mutex, NULL);
- switch (scan_state) {
- case SCAN_DISABLE:
- case SCAN_BACK_OP:
- rfctl->offch_state = OFFCHS_NONE;
- break;
- case SCAN_START:
- case SCAN_LEAVING_OP:
- rfctl->offch_state = OFFCHS_LEAVING_OP;
- break;
- case SCAN_ENTER:
- case SCAN_LEAVE_OP:
- rfctl->offch_state = OFFCHS_LEAVE_OP;
- break;
- case SCAN_COMPLETE:
- case SCAN_BACKING_OP:
- rfctl->offch_state = OFFCHS_BACKING_OP;
- break;
- default:
- break;
- }
- _exit_critical_mutex(&rfctl->offch_mutex, NULL);
- }
- u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)
- {
- struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
- #ifdef DBG_CHECK_FW_PS_STATE
- struct dvobj_priv *dvobj = padapter->dvobj;
- struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
- #endif
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct ss_res *ss = &pmlmeext->sitesurvey_res;
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
- #endif
- u8 val8;
- #ifdef CONFIG_P2P
- struct wifidirect_info *pwdinfo = &padapter->wdinfo;
- #endif
- #ifdef DBG_CHECK_FW_PS_STATE
- if (rtw_fw_ps_state(padapter) == _FAIL) {
- RTW_INFO("scan without leave 32k\n");
- pdbgpriv->dbg_scan_pwr_state_cnt++;
- }
- #endif /* DBG_CHECK_FW_PS_STATE */
- /* increase channel idx */
- if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS))
- ss->channel_idx++;
- /* update scan state to next state (assigned by previous cmd hdl) */
- if (mlmeext_scan_state(pmlmeext) != mlmeext_scan_next_state(pmlmeext))
- mlmeext_set_scan_state(pmlmeext, mlmeext_scan_next_state(pmlmeext));
- operation_by_state:
- switch (mlmeext_scan_state(pmlmeext)) {
- case SCAN_DISABLE:
- /*
- * SW parameter initialization
- */
- sitesurvey_res_reset(padapter, pparm);
- mlmeext_set_scan_state(pmlmeext, SCAN_START);
- goto operation_by_state;
- case SCAN_START:
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- if ((pwdev_priv->pno_mac_addr[0] != 0xFF)
- && (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE)
- && (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) {
- u16 seq_num;
- rtw_hal_pno_random_gen_mac_addr(padapter);
- rtw_hal_set_hw_mac_addr(padapter, pwdev_priv->pno_mac_addr);
- get_random_bytes(&seq_num, 2);
- pwdev_priv->pno_scan_seq_num = seq_num & 0xFFF;
- RTW_INFO("%s pno_scan_seq_num %d\n", __func__,
- pwdev_priv->pno_scan_seq_num);
- }
- #endif
- /*
- * prepare to leave operating channel
- */
- #ifdef CONFIG_MCC_MODE
- rtw_hal_set_mcc_setting_scan_start(padapter);
- #endif /* CONFIG_MCC_MODE */
- /* apply rx ampdu setting */
- if (ss->rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID
- || ss->rx_ampdu_size != RX_AMPDU_SIZE_INVALID)
- rtw_rx_ampdu_apply(padapter);
- /* clear HW TX queue before scan */
- rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
- rtw_hal_macid_sleep_all_used(padapter);
- /* power save state announcement */
- if (rtw_ps_annc(padapter, 1)) {
- mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);
- mlmeext_set_scan_next_state(pmlmeext, SCAN_ENTER);
- set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */
- } else {
- mlmeext_set_scan_state(pmlmeext, SCAN_ENTER);
- goto operation_by_state;
- }
- break;
- case SCAN_ENTER:
- /*
- * HW register and DM setting for enter scan
- */
- rtw_phydm_ability_backup(padapter);
- sitesurvey_set_igi(padapter);
- /* config dynamic functions for off channel */
- rtw_phydm_func_for_offchannel(padapter);
- /* set MSR to no link state */
- sitesurvey_set_msr(padapter, _TRUE);
- val8 = 1; /* under site survey */
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
- mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
- goto operation_by_state;
- case SCAN_PROCESS: {
- u8 scan_ch;
- RT_SCAN_TYPE scan_type;
- u8 next_state;
- u32 scan_ms;
- #ifdef CONFIG_RTW_ACS
- if (IS_ACS_ENABLE(padapter))
- rtw_acs_get_rst(padapter);
- #endif
- next_state = sitesurvey_pick_ch_behavior(padapter, &scan_ch, &scan_type);
- if (next_state != SCAN_PROCESS) {
- mlmeext_set_scan_state(pmlmeext, next_state);
- goto operation_by_state;
- }
- /* still SCAN_PROCESS state */
- #ifdef DBG_SITESURVEY
- #ifdef CONFIG_P2P
- RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c%c\n"
- , FUNC_ADPT_ARG(padapter)
- , mlmeext_scan_state_str(pmlmeext)
- , scan_ch
- , pwdinfo->find_phase_state_exchange_cnt, ss->channel_idx
- , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
- , scan_type ? 'A' : 'P', ss->scan_mode ? 'A' : 'P'
- , ss->ssid[0].SsidLength ? 'S' : ' '
- , ss->dfs_ch_ssid_scan ? 'D' : ' '
- );
- #else
- RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (idx:%d) at %dms, %c%c%c%c\n"
- , FUNC_ADPT_ARG(padapter)
- , mlmeext_scan_state_str(pmlmeext)
- , scan_ch
- , ss->channel_idx
- , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
- , scan_type ? 'A' : 'P', ss->scan_mode ? 'A' : 'P'
- , ss->ssid[0].SsidLength ? 'S' : ' '
- , ss->dfs_ch_ssid_scan ? 'D' : ' '
- );
- #endif /* CONFIG_P2P */
- #endif /*DBG_SITESURVEY*/
- #ifdef DBG_FIXED_CHAN
- if (pmlmeext->fixed_chan != 0xff)
- RTW_INFO(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
- #endif
- site_survey(padapter, scan_ch, scan_type);
- #if defined(CONFIG_ATMEL_RC_PATCH)
- if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
- scan_ms = 20;
- else
- scan_ms = 40;
- #else
- #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
- if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter))
- scan_ms = rtw_acs_get_adv_st(padapter);
- else
- #endif /*CONFIG_RTW_ACS*/
- scan_ms = ss->scan_ch_ms;
- #endif
- #if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
- if (ss->is_sw_antdiv_bl_scan)
- scan_ms = scan_ms / 2;
- #endif
- #ifdef CONFIG_RTW_ACS
- if (IS_ACS_ENABLE(padapter)) {
- if (pparm->token)
- rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_IEEE_11K_HIGH);
- else
- rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_ACS);
- }
- #endif
- #ifdef CONFIG_BACKGROUND_NOISE_MONITOR
- if (IS_NM_ENABLE(padapter))
- rtw_noise_measure(padapter, scan_ch, _FALSE, 0, scan_ms / 2);
- #endif
- set_survey_timer(pmlmeext, scan_ms);
- break;
- }
- #ifdef CONFIG_SCAN_BACKOP
- case SCAN_BACKING_OP: {
- u8 back_ch, back_bw, back_ch_offset;
- u8 need_ch_setting_union = _TRUE;
- #ifdef CONFIG_MCC_MODE
- need_ch_setting_union = rtw_hal_mcc_change_scan_flag(padapter,
- &back_ch, &back_bw, &back_ch_offset);
- #endif /* CONFIG_MCC_MODE */
- if (need_ch_setting_union) {
- if (rtw_mi_get_ch_setting_union(padapter, &back_ch, &back_bw, &back_ch_offset) == 0)
- rtw_warn_on(1);
- }
- #ifdef DBG_SITESURVEY
- RTW_INFO(FUNC_ADPT_FMT" %s ch:%u, bw:%u, offset:%u at %dms\n"
- , FUNC_ADPT_ARG(padapter)
- , mlmeext_scan_state_str(pmlmeext)
- , back_ch, back_bw, back_ch_offset
- , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
- );
- #endif /*DBG_SITESURVEY*/
- set_channel_bwmode(padapter, back_ch, back_ch_offset, back_bw);
- sitesurvey_set_msr(padapter, _FALSE);
- val8 = 0; /* survey done */
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
- if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) {
- sitesurvey_set_igi(padapter);
- rtw_hal_macid_wakeup_all_used(padapter);
- rtw_ps_annc(padapter, 0);
- }
- mlmeext_set_scan_state(pmlmeext, SCAN_BACK_OP);
- ss->backop_time = rtw_get_current_time();
- if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_TX_RESUME))
- rtw_mi_os_xmit_schedule(padapter);
- goto operation_by_state;
- }
- case SCAN_BACK_OP:
- if (rtw_get_passing_time_ms(ss->backop_time) >= ss->backop_ms
- || pmlmeext->scan_abort
- ) {
- mlmeext_set_scan_state(pmlmeext, SCAN_LEAVING_OP);
- goto operation_by_state;
- }
- set_survey_timer(pmlmeext, 50);
- break;
- case SCAN_LEAVING_OP:
- /*
- * prepare to leave operating channel
- */
- /* clear HW TX queue before scan */
- rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
- rtw_hal_macid_sleep_all_used(padapter);
- if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)
- && rtw_ps_annc(padapter, 1)
- ) {
- mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);
- mlmeext_set_scan_next_state(pmlmeext, SCAN_LEAVE_OP);
- set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */
- } else {
- mlmeext_set_scan_state(pmlmeext, SCAN_LEAVE_OP);
- goto operation_by_state;
- }
- break;
- case SCAN_LEAVE_OP:
- /*
- * HW register and DM setting for enter scan
- */
- if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC))
- sitesurvey_set_igi(padapter);
- sitesurvey_set_msr(padapter, _TRUE);
- val8 = 1; /* under site survey */
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
- mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
- goto operation_by_state;
- #endif /* CONFIG_SCAN_BACKOP */
- #if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
- case SCAN_SW_ANTDIV_BL:
- /*
- * 20100721
- * For SW antenna diversity before link, it needs to switch to another antenna and scan again.
- * It compares the scan result and select better one to do connection.
- */
- ss->bss_cnt = 0;
- ss->channel_idx = 0;
- ss->is_sw_antdiv_bl_scan = 1;
- mlmeext_set_scan_next_state(pmlmeext, SCAN_PROCESS);
- set_survey_timer(pmlmeext, ss->scan_ch_ms);
- break;
- #endif
- #ifdef CONFIG_P2P
- case SCAN_TO_P2P_LISTEN:
- /*
- * Set the P2P State to the listen state of find phase
- * and set the current channel to the listen channel
- */
- set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
- rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
- /* turn on phy-dynamic functions */
- rtw_phydm_ability_restore(padapter);
- sitesurvey_set_igi(padapter);
- mlmeext_set_scan_state(pmlmeext, SCAN_P2P_LISTEN);
- _set_timer(&pwdinfo->find_phase_timer, (u32)((u32)pwdinfo->listen_dwell * 100));
- break;
- case SCAN_P2P_LISTEN:
- mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
- ss->channel_idx = 0;
- goto operation_by_state;
- #endif /* CONFIG_P2P */
- case SCAN_COMPLETE:
- #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
- rtw_hal_set_hw_mac_addr(padapter, adapter_mac_addr(padapter));
- #endif
- #ifdef CONFIG_P2P
- if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
- || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
- ) {
- #ifdef CONFIG_CONCURRENT_MODE
- if (pwdinfo->driver_interface == DRIVER_WEXT) {
- if (rtw_mi_check_status(padapter, MI_LINKED))
- _set_timer(&pwdinfo->ap_p2p_switch_timer, 500);
- }
- #endif
- rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
- }
- rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
- #endif /* CONFIG_P2P */
- /* switch channel */
- survey_done_set_ch_bw(padapter);
- sitesurvey_set_msr(padapter, _FALSE);
- val8 = 0; /* survey done */
- rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
- /* turn on phy-dynamic functions */
- rtw_phydm_ability_restore(padapter);
- sitesurvey_set_igi(padapter);
- #ifdef CONFIG_MCC_MODE
- /* start MCC fail, then tx null data */
- if (!rtw_hal_set_mcc_setting_scan_complete(padapter))
- #endif
- {
- rtw_hal_macid_wakeup_all_used(padapter);
- rtw_ps_annc(padapter, 0);
- }
- /* apply rx ampdu setting */
- rtw_rx_ampdu_apply(padapter);
- mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
- report_surveydone_event(padapter);
- #ifdef CONFIG_RTW_ACS
- if (IS_ACS_ENABLE(padapter))
- rtw_acs_select_best_chan(padapter);
- #endif
- #if defined(CONFIG_BACKGROUND_NOISE_MONITOR) && defined(DBG_NOISE_MONITOR)
- if (IS_NM_ENABLE(padapter))
- rtw_noise_info_dump(RTW_DBGDUMP, padapter);
- #endif
- issue_action_BSSCoexistPacket(padapter);
- issue_action_BSSCoexistPacket(padapter);
- issue_action_BSSCoexistPacket(padapter);
- #ifdef CONFIG_RTW_80211K
- if (ss->token)
- rm_post_event(padapter, ss->token, RM_EV_survey_done);
- #endif /* CONFIG_RTW_80211K */
- break;
- }
- return H2C_SUCCESS;
- }
- u8 setauth_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (pparm->mode < 4)
- pmlmeinfo->auth_algo = pparm->mode;
- return H2C_SUCCESS;
- }
- /*
- SEC CAM Entry format (32 bytes)
- DW0 - MAC_ADDR[15:0] | Valid[15] | MFB[14:8] | RSVD[7] | GK[6] | MIC_KEY[5] | SEC_TYPE[4:2] | KID[1:0]
- DW0 - MAC_ADDR[15:0] | Valid[15] |RSVD[14:9] | RPT_MODE[8] | SPP_MODE[7] | GK[6] | MIC_KEY[5] | SEC_TYPE[4:2] | KID[1:0] (92E/8812A/8814A)
- DW1 - MAC_ADDR[47:16]
- DW2 - KEY[31:0]
- DW3 - KEY[63:32]
- DW4 - KEY[95:64]
- DW5 - KEY[127:96]
- DW6 - RSVD
- DW7 - RSVD
- */
- /*Set WEP key or Group Key*/
- u8 setkey_hdl(_adapter *padapter, u8 *pbuf)
- {
- u16 ctrl = 0;
- s16 cam_id = 0;
- struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- u8 *addr;
- bool used = _FALSE;
- /* main tx key for wep. */
- if (pparm->set_tx)
- pmlmeinfo->key_index = pparm->keyid;
- #ifdef CONFIG_CONCURRENT_MODE
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE))
- cam_id = rtw_iface_bcmc_id_get(padapter);
- else
- #endif
- cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid, 1, &used);
- if (cam_id < 0)
- goto enable_mc;
- #ifndef CONFIG_CONCURRENT_MODE
- if (cam_id >= 0 && cam_id <= 3) {
- /* default key camid */
- addr = null_addr;
- } else
- #endif
- {
- /* not default key camid */
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
- /* group TX, force sec cam entry_id */
- addr = adapter_mac_addr(padapter);
- } else {
- /* group RX, searched by A2 (TA) */
- addr = get_bssid(&padapter->mlmepriv);
- }
- }
- /* cam entry searched is pairwise key */
- if (used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _FALSE) {
- s16 camid_clr;
- RTW_PRINT(FUNC_ADPT_FMT" group key with "MAC_FMT" id:%u the same key id as pairwise key\n"
- , FUNC_ADPT_ARG(padapter), MAC_ARG(addr), pparm->keyid);
- /* HW has problem to distinguish this group key with existing pairwise key, stop HW enc and dec for BMC */
- rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH);
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL);
- /* clear group key */
- while ((camid_clr = rtw_camid_search(padapter, addr, -1, 1)) >= 0) {
- RTW_PRINT("clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(addr), camid_clr);
- clear_cam_entry(padapter, camid_clr);
- rtw_camid_free(padapter, camid_clr);
- }
- goto enable_mc;
- }
- ctrl = BIT(15) | BIT(6) | ((pparm->algorithm) << 2) | pparm->keyid;
- RTW_PRINT("set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
- , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
- write_cam(padapter, cam_id, ctrl, addr, pparm->key);
- /* if ((cam_id > 3) && (((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)))*/
- #ifdef CONFIG_CONCURRENT_MODE
- if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
- if (is_wep_enc(pparm->algorithm)) {
- padapter->securitypriv.dot11Def_camid[pparm->keyid] = cam_id;
- padapter->securitypriv.dot118021x_bmc_cam_id =
- padapter->securitypriv.dot11Def_camid[padapter->securitypriv.dot11PrivacyKeyIndex];
- RTW_PRINT("wep group key - force camid:%d\n", padapter->securitypriv.dot118021x_bmc_cam_id);
- } else {
- /*u8 org_cam_id = padapter->securitypriv.dot118021x_bmc_cam_id;*/
- /*force GK's cam id*/
- padapter->securitypriv.dot118021x_bmc_cam_id = cam_id;
- /* for GTK rekey
- if ((org_cam_id != INVALID_SEC_MAC_CAM_ID) &&
- (org_cam_id != cam_id)) {
- RTW_PRINT("clear group key for addr:"MAC_FMT", org_camid:%d new_camid:%d\n", MAC_ARG(addr), org_cam_id, cam_id);
- clear_cam_entry(padapter, org_cam_id);
- rtw_camid_free(padapter, org_cam_id);
- }*/
- }
- }
- #endif
- #ifndef CONFIG_CONCURRENT_MODE
- if (cam_id >= 0 && cam_id <= 3)
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)_TRUE);
- #endif
- /* 8814au should set both broadcast and unicast CAM entry for WEP key in STA mode */
- if (is_wep_enc(pparm->algorithm) && check_mlmeinfo_state(pmlmeext, WIFI_FW_STATION_STATE) &&
- _rtw_camctl_chk_cap(padapter, SEC_CAP_CHK_BMC)) {
- struct set_stakey_parm sta_pparm;
- _rtw_memset(&sta_pparm, 0, sizeof(struct set_stakey_parm));
- sta_pparm.algorithm = pparm->algorithm;
- sta_pparm.keyid = pparm->keyid;
- _rtw_memcpy(sta_pparm.key, pparm->key, 16);
- _rtw_memcpy(sta_pparm.addr, get_bssid(&padapter->mlmepriv), ETH_ALEN);
- set_stakey_hdl(padapter, (u8 *)&sta_pparm);
- }
- enable_mc:
- /* allow multicast packets to driver */
- rtw_hal_set_hwreg(padapter, HW_VAR_ON_RCR_AM, null_addr);
- return H2C_SUCCESS;
- }
- void rtw_ap_wep_pk_setting(_adapter *adapter, struct sta_info *psta)
- {
- struct security_priv *psecuritypriv = &(adapter->securitypriv);
- struct set_stakey_parm sta_pparm;
- sint keyid;
- if (!is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm))
- return;
- for (keyid = 0; keyid < 4; keyid++) {
- if ((psecuritypriv->key_mask & BIT(keyid)) && (keyid == psecuritypriv->dot11PrivacyKeyIndex)) {
- sta_pparm.algorithm = psecuritypriv->dot11PrivacyAlgrthm;
- sta_pparm.keyid = keyid;
- sta_pparm.gk = 0;
- _rtw_memcpy(sta_pparm.key, &(psecuritypriv->dot11DefKey[keyid].skey[0]), 16);
- _rtw_memcpy(sta_pparm.addr, psta->cmn.mac_addr, ETH_ALEN);
- RTW_PRINT(FUNC_ADPT_FMT"set WEP - PK with "MAC_FMT" keyid:%u\n"
- , FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr), keyid);
- set_stakey_hdl(adapter, (u8 *)&sta_pparm);
- }
- }
- }
- u8 set_stakey_hdl(_adapter *padapter, u8 *pbuf)
- {
- u16 ctrl = 0;
- s16 cam_id = 0;
- bool used;
- u8 ret = H2C_SUCCESS;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *psta;
- if (pparm->algorithm == _NO_PRIVACY_)
- goto write_to_cam;
- psta = rtw_get_stainfo(pstapriv, pparm->addr);
- if (!psta) {
- RTW_PRINT("%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));
- ret = H2C_REJECTED;
- goto exit;
- }
- pmlmeinfo->enc_algo = pparm->algorithm;
- cam_id = rtw_camid_alloc(padapter, psta, pparm->keyid, pparm->gk, &used);
- if (cam_id < 0)
- goto exit;
- /* cam entry searched is group key when setting pariwise key */
- if (!pparm->gk && used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _TRUE) {
- s16 camid_clr;
- RTW_PRINT(FUNC_ADPT_FMT" pairwise key with "MAC_FMT" id:%u the same key id as group key\n"
- , FUNC_ADPT_ARG(padapter), MAC_ARG(pparm->addr), pparm->keyid);
- /* HW has problem to distinguish this pairwise key with existing group key, stop HW enc and dec for BMC */
- rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH);
- rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL);
- /* clear group key */
- while ((camid_clr = rtw_camid_search(padapter, pparm->addr, -1, 1)) >= 0) {
- RTW_PRINT("clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), camid_clr);
- clear_cam_entry(padapter, camid_clr);
- rtw_camid_free(padapter, camid_clr);
- }
- }
- write_to_cam:
- if (pparm->algorithm == _NO_PRIVACY_) {
- while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1, -1)) >= 0) {
- RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);
- clear_cam_entry(padapter, cam_id);
- rtw_camid_free(padapter, cam_id);
- }
- } else {
- RTW_PRINT("set %s key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
- , pparm->gk ? "group" : "pairwise"
- , cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));
- ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
- if (pparm->gk)
- ctrl |= BIT(6);
- write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
- }
- ret = H2C_SUCCESS_RSP;
- exit:
- return ret;
- }
- u8 add_ba_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
- if (!psta)
- return H2C_SUCCESS;
- #ifdef CONFIG_80211N_HT
- if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
- ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
- /* pmlmeinfo->ADDBA_retry_count = 0; */
- /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
- /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
- issue_addba_req(padapter, pparm->addr, (u8)pparm->tid);
- _set_timer(&psta->addba_retry_timer, ADDBA_TO);
- }
- #ifdef CONFIG_TDLS
- else if ((psta->tdls_sta_state & TDLS_LINKED_STATE) &&
- (psta->htpriv.ht_option == _TRUE) &&
- (psta->htpriv.ampdu_enable == _TRUE)) {
- issue_addba_req(padapter, pparm->addr, (u8)pparm->tid);
- _set_timer(&psta->addba_retry_timer, ADDBA_TO);
- }
- #endif /* CONFIG */
- else
- psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
- #endif /* CONFIG_80211N_HT */
- return H2C_SUCCESS;
- }
- u8 add_ba_rsp_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- struct addBaRsp_parm *pparm = (struct addBaRsp_parm *)pbuf;
- struct recv_reorder_ctrl *preorder_ctrl;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *psta;
- u8 ret = _TRUE;
- psta = rtw_get_stainfo(pstapriv, pparm->addr);
- if (!psta)
- goto exit;
- preorder_ctrl = &psta->recvreorder_ctrl[pparm->tid];
- ret = issue_addba_rsp_wait_ack(padapter, pparm->addr, pparm->tid, pparm->status, pparm->size, 3, 50);
- #ifdef CONFIG_UPDATE_INDICATE_SEQ_WHILE_PROCESS_ADDBA_REQ
- /* status = 0 means accept this addba req, so update indicate seq = start_seq under this compile flag */
- if (pparm->status == 0) {
- preorder_ctrl->indicate_seq = pparm->start_seq;
- #ifdef DBG_RX_SEQ
- RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_UPDATE indicate_seq:%d, start_seq:%d\n"
- , FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, pparm->start_seq);
- #endif
- }
- #else
- preorder_ctrl->indicate_seq = 0xffff;
- #ifdef DBG_RX_SEQ
- RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_CLEAR indicate_seq:%d, start_seq:%d\n"
- , FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, pparm->start_seq);
- #endif
- #endif
- /*
- * status = 0 means accept this addba req
- * status = 37 means reject this addba req
- */
- if (pparm->status == 0) {
- preorder_ctrl->enable = _TRUE;
- preorder_ctrl->ampdu_size = pparm->size;
- } else if (pparm->status == 37)
- preorder_ctrl->enable = _FALSE;
- exit:
- return H2C_SUCCESS;
- }
- u8 chk_bmc_sleepq_cmd(_adapter *padapter)
- {
- struct cmd_obj *ph2c;
- struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
- u8 res = _SUCCESS;
- ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (ph2c == NULL) {
- res = _FAIL;
- goto exit;
- }
- init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
- exit:
- return res;
- }
- u8 set_tx_beacon_cmd(_adapter *padapter)
- {
- struct cmd_obj *ph2c;
- struct Tx_Beacon_param *ptxBeacon_parm;
- struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- u8 res = _SUCCESS;
- int len_diff = 0;
- ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
- if (ph2c == NULL) {
- res = _FAIL;
- goto exit;
- }
- ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param));
- if (ptxBeacon_parm == NULL) {
- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
- res = _FAIL;
- goto exit;
- }
- _rtw_memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
- len_diff = update_hidden_ssid(
- ptxBeacon_parm->network.IEs + _BEACON_IE_OFFSET_
- , ptxBeacon_parm->network.IELength - _BEACON_IE_OFFSET_
- , pmlmeinfo->hidden_ssid_mode
- );
- ptxBeacon_parm->network.IELength += len_diff;
- init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
- exit:
- return res;
- }
- u8 mlme_evt_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- u8 evt_code, evt_seq;
- u16 evt_sz;
- uint *peventbuf;
- void (*event_callback)(_adapter *dev, u8 *pbuf);
- struct evt_priv *pevt_priv = &(padapter->evtpriv);
- if (pbuf == NULL)
- goto _abort_event_;
- peventbuf = (uint *)pbuf;
- evt_sz = (u16)(*peventbuf & 0xffff);
- evt_seq = (u8)((*peventbuf >> 24) & 0x7f);
- evt_code = (u8)((*peventbuf >> 16) & 0xff);
- #ifdef CHECK_EVENT_SEQ
- /* checking event sequence... */
- if (evt_seq != (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f)) {
- pevt_priv->event_seq = (evt_seq + 1) & 0x7f;
- goto _abort_event_;
- }
- #endif
- /* checking if event code is valid */
- if (evt_code >= MAX_C2HEVT) {
- goto _abort_event_;
- }
- /* checking if event size match the event parm size */
- if ((wlanevents[evt_code].parmsize != 0) &&
- (wlanevents[evt_code].parmsize != evt_sz)) {
- goto _abort_event_;
- }
- ATOMIC_INC(&pevt_priv->event_seq);
- peventbuf += 2;
- if (peventbuf) {
- event_callback = wlanevents[evt_code].event_callback;
- event_callback(padapter, (u8 *)peventbuf);
- pevt_priv->evt_done_cnt++;
- }
- _abort_event_:
- return H2C_SUCCESS;
- }
- u8 h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
- return H2C_SUCCESS;
- }
- u8 chk_bmc_sleepq_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- #ifdef CONFIG_AP_MODE
- _irqL irqL;
- struct sta_info *psta_bmc;
- _list *xmitframe_plist, *xmitframe_phead;
- struct xmit_frame *pxmitframe = NULL;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
- /* for BC/MC Frames */
- psta_bmc = rtw_get_bcmc_stainfo(padapter);
- if (!psta_bmc)
- return H2C_SUCCESS;
- if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) {
- #ifndef CONFIG_PCI_HCI
- rtw_msleep_os(10);/* 10ms, ATIM(HIQ) Windows */
- #endif
- /* _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL); */
- _enter_critical_bh(&pxmitpriv->lock, &irqL);
- xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
- xmitframe_plist = get_next(xmitframe_phead);
- while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {
- pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
- xmitframe_plist = get_next(xmitframe_plist);
- rtw_list_delete(&pxmitframe->list);
- psta_bmc->sleepq_len--;
- if (psta_bmc->sleepq_len > 0)
- pxmitframe->attrib.mdata = 1;
- else
- pxmitframe->attrib.mdata = 0;
- pxmitframe->attrib.triggered = 1;
- if (xmitframe_hiq_filter(pxmitframe) == _TRUE)
- pxmitframe->attrib.qsel = QSLT_HIGH;/* HIQ */
- #if 0
- _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
- if (rtw_hal_xmit(padapter, pxmitframe) == _TRUE)
- rtw_os_xmit_complete(padapter, pxmitframe);
- _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
- #endif
- rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
- }
- /* _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL); */
- _exit_critical_bh(&pxmitpriv->lock, &irqL);
- if (rtw_get_intf_type(padapter) != RTW_PCIE) {
- /* check hi queue and bmc_sleepq */
- rtw_chk_hi_queue_cmd(padapter);
- }
- }
- #endif
- return H2C_SUCCESS;
- }
- u8 tx_beacon_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- /*RTW_INFO(FUNC_ADPT_FMT, FUNC_ADPT_ARG(padapter));*/
- #ifdef CONFIG_SWTIMER_BASED_TXBCN
- tx_beacon_handlder(padapter->dvobj);
- #else
- if (send_beacon(padapter) == _FAIL) {
- RTW_INFO("issue_beacon, fail!\n");
- return H2C_PARAMETERS_ERROR;
- }
- /* tx bc/mc frames after update TIM */
- chk_bmc_sleepq_hdl(padapter, NULL);
- #endif
- return H2C_SUCCESS;
- }
- /*
- * according to channel
- * add/remove WLAN_BSSID_EX.IEs's ERP ie
- * set WLAN_BSSID_EX.SupportedRates
- * update WLAN_BSSID_EX.IEs's Supported Rate and Extended Supported Rate ie
- */
- void change_band_update_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 ch)
- {
- u8 network_type, rate_len, total_rate_len, remainder_rate_len;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
- u8 erpinfo = 0x4;
- if (ch >= 36) {
- network_type = WIRELESS_11A;
- total_rate_len = IEEE80211_NUM_OFDM_RATESLEN;
- rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_);
- #ifdef CONFIG_80211AC_VHT
- /* if channel in 5G band, then add vht ie . */
- if ((pmlmepriv->htpriv.ht_option == _TRUE)
- && REGSTY_IS_11AC_ENABLE(&padapter->registrypriv)
- && is_supported_vht(padapter->registrypriv.wireless_mode)
- && (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))
- ) {
- if (REGSTY_IS_11AC_AUTO(&padapter->registrypriv)
- || pmlmepriv->ori_vht_en)
- rtw_vht_ies_attach(padapter, pnetwork);
- }
- #endif
- } else {
- network_type = WIRELESS_11BG;
- total_rate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;
- rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1);
- #ifdef CONFIG_80211AC_VHT
- rtw_vht_ies_detach(padapter, pnetwork);
- #endif
- }
- rtw_set_supported_rate(pnetwork->SupportedRates, network_type);
- UpdateBrateTbl(padapter, pnetwork->SupportedRates);
- if (total_rate_len > 8) {
- rate_len = 8;
- remainder_rate_len = total_rate_len - 8;
- } else {
- rate_len = total_rate_len;
- remainder_rate_len = 0;
- }
- rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len);
- if (remainder_rate_len)
- rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates + 8), remainder_rate_len);
- else
- rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_);
- pnetwork->Length = get_WLAN_BSSID_EX_sz(pnetwork);
- }
- void rtw_join_done_chk_ch(_adapter *adapter, int join_res)
- {
- #define DUMP_ADAPTERS_STATUS 0
- struct dvobj_priv *dvobj;
- _adapter *iface;
- struct mlme_priv *mlme;
- struct mlme_ext_priv *mlmeext;
- u8 u_ch, u_offset, u_bw;
- int i;
- dvobj = adapter_to_dvobj(adapter);
- if (DUMP_ADAPTERS_STATUS) {
- RTW_INFO(FUNC_ADPT_FMT" enter\n", FUNC_ADPT_ARG(adapter));
- dump_adapters_status(RTW_DBGDUMP , dvobj);
- }
- if (join_res >= 0) {
- #ifdef CONFIG_MCC_MODE
- /* MCC setting success, don't go to ch union process */
- if (rtw_hal_set_mcc_setting_join_done_chk_ch(adapter))
- return;
- #endif /* CONFIG_MCC_MODE */
- if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset) <= 0) {
- dump_adapters_status(RTW_DBGDUMP , dvobj);
- rtw_warn_on(1);
- }
- for (i = 0; i < dvobj->iface_nums; i++) {
- iface = dvobj->padapters[i];
- mlme = &iface->mlmepriv;
- mlmeext = &iface->mlmeextpriv;
- if (!iface || iface == adapter)
- continue;
- if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface))
- && check_fwstate(mlme, WIFI_ASOC_STATE)
- ) {
- u8 ori_ch, ori_bw, ori_offset;
- bool is_grouped = rtw_is_chbw_grouped(u_ch, u_bw, u_offset
- , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);
- if (is_grouped == _FALSE) {
- /* handle AP which need to switch ch setting */
- ori_ch = mlmeext->cur_channel;
- ori_bw = mlmeext->cur_bwmode;
- ori_offset = mlmeext->cur_ch_offset;
- /* restore original bw, adjust bw by registry setting on target ch */
- mlmeext->cur_bwmode = mlme->ori_bw;
- mlmeext->cur_channel = u_ch;
- rtw_adjust_chbw(iface, mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset);
- #ifdef CONFIG_RTW_MESH
- if (MLME_IS_MESH(iface))
- rtw_mesh_adjust_chbw(mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset);
- #endif
- rtw_chset_sync_chbw(adapter_to_chset(adapter)
- , &mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset
- , &u_ch, &u_bw, &u_offset);
- RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u\n", FUNC_ADPT_ARG(iface)
- , ori_ch, ori_bw, ori_offset
- , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);
- rtw_ap_update_bss_chbw(iface, &(mlmeext->mlmext_info.network)
- , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);
- _rtw_memcpy(&(mlme->cur_network.network), &(mlmeext->mlmext_info.network), sizeof(WLAN_BSSID_EX));
- rtw_start_bss_hdl_after_chbw_decided(iface);
- if (MLME_IS_GO(iface) || MLME_IS_MESH(iface)) { /* pure AP is not needed*/
- #if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
- u8 ht_option = 0;
- #ifdef CONFIG_80211N_HT
- ht_option = mlme->htpriv.ht_option;
- #endif
- rtw_cfg80211_ch_switch_notify(iface
- , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset
- , ht_option);
- #endif
- }
- }
- clr_fwstate(mlme, WIFI_OP_CH_SWITCHING);
- update_beacon(iface, 0xFF, NULL, _TRUE);
- }
- }
- #ifdef CONFIG_DFS_MASTER
- rtw_dfs_rd_en_decision(adapter, MLME_STA_CONNECTED, 0);
- #endif
- } else {
- for (i = 0; i < dvobj->iface_nums; i++) {
- iface = dvobj->padapters[i];
- mlme = &iface->mlmepriv;
- mlmeext = &iface->mlmeextpriv;
- if (!iface || iface == adapter)
- continue;
- if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface))
- && check_fwstate(mlme, WIFI_ASOC_STATE)
- ) {
- clr_fwstate(mlme, WIFI_OP_CH_SWITCHING);
- update_beacon(iface, 0xFF, NULL, _TRUE);
- }
- }
- #ifdef CONFIG_DFS_MASTER
- rtw_dfs_rd_en_decision(adapter, MLME_STA_DISCONNECTED, 0);
- #endif
- }
- if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset)) {
- RTW_INFO(FUNC_ADPT_FMT" union:%u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
- set_channel_bwmode(adapter, u_ch, u_offset, u_bw);
- rtw_mi_update_union_chan_inf(adapter, u_ch, u_offset, u_bw);
- }
- if (DUMP_ADAPTERS_STATUS) {
- RTW_INFO(FUNC_ADPT_FMT" exit\n", FUNC_ADPT_ARG(adapter));
- dump_adapters_status(RTW_DBGDUMP , dvobj);
- }
- }
- int rtw_chk_start_clnt_join(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
- {
- #ifdef CONFIG_CONCURRENT_MODE
- bool chbw_allow = _TRUE;
- #endif
- bool connect_allow = _TRUE;
- struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
- u8 cur_ch, cur_bw, cur_ch_offset;
- u8 u_ch, u_offset, u_bw;
- u_ch = cur_ch = pmlmeext->cur_channel;
- u_bw = cur_bw = pmlmeext->cur_bwmode;
- u_offset = cur_ch_offset = pmlmeext->cur_ch_offset;
- if (!ch || !bw || !offset) {
- connect_allow = _FALSE;
- rtw_warn_on(1);
- goto exit;
- }
- if (cur_ch == 0) {
- connect_allow = _FALSE;
- RTW_ERR(FUNC_ADPT_FMT" cur_ch:%u\n"
- , FUNC_ADPT_ARG(adapter), cur_ch);
- rtw_warn_on(1);
- goto exit;
- }
- RTW_INFO(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
- #ifdef CONFIG_CONCURRENT_MODE
- {
- struct dvobj_priv *dvobj;
- _adapter *iface;
- struct mlme_priv *mlme;
- struct mlme_ext_priv *mlmeext;
- struct mi_state mstate;
- int i;
- dvobj = adapter_to_dvobj(adapter);
- rtw_mi_status_no_self(adapter, &mstate);
- RTW_INFO(FUNC_ADPT_FMT" others ld_sta_num:%u, ap_num:%u, mesh_num:%u\n"
- , FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate)
- , MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate));
- if (!MSTATE_STA_LD_NUM(&mstate) && !MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {
- /* consider linking STA? */
- goto connect_allow_hdl;
- }
- if (rtw_mi_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset) <= 0) {
- dump_adapters_status(RTW_DBGDUMP , dvobj);
- rtw_warn_on(1);
- }
- RTW_INFO(FUNC_ADPT_FMT" others union:%u,%u,%u\n"
- , FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
- /* chbw_allow? */
- chbw_allow = rtw_is_chbw_grouped(pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset
- , u_ch, u_bw, u_offset);
- RTW_INFO(FUNC_ADPT_FMT" chbw_allow:%d\n"
- , FUNC_ADPT_ARG(adapter), chbw_allow);
- #ifdef CONFIG_MCC_MODE
- /* check setting success, don't go to ch union process */
- if (rtw_hal_set_mcc_setting_chk_start_clnt_join(adapter, &u_ch, &u_bw, &u_offset, chbw_allow))
- goto exit;
- #endif
- if (chbw_allow == _TRUE) {
- rtw_sync_chbw(&cur_ch, &cur_bw, &cur_ch_offset, &u_ch, &u_bw, &u_offset);
- rtw_warn_on(cur_ch != pmlmeext->cur_channel);
- rtw_warn_on(cur_bw != pmlmeext->cur_bwmode);
- rtw_warn_on(cur_ch_offset != pmlmeext->cur_ch_offset);
- goto connect_allow_hdl;
- }
- #ifdef CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT
- /* chbw_allow is _FALSE, connect allow? */
- for (i = 0; i < dvobj->iface_nums; i++) {
- iface = dvobj->padapters[i];
- mlme = &iface->mlmepriv;
- mlmeext = &iface->mlmeextpriv;
- if (check_fwstate(mlme, WIFI_STATION_STATE)
- && check_fwstate(mlme, WIFI_ASOC_STATE)
- #if defined(CONFIG_P2P)
- && rtw_p2p_chk_state(&(iface->wdinfo), P2P_STATE_NONE)
- #endif
- ) {
- connect_allow = _FALSE;
- break;
- }
- }
- #endif /* CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT */
- if (MSTATE_STA_LD_NUM(&mstate) + MSTATE_AP_LD_NUM(&mstate) + MSTATE_MESH_LD_NUM(&mstate) >= 4)
- connect_allow = _FALSE;
- RTW_INFO(FUNC_ADPT_FMT" connect_allow:%d\n"
- , FUNC_ADPT_ARG(adapter), connect_allow);
- if (connect_allow == _FALSE)
- goto exit;
- connect_allow_hdl:
- /* connect_allow == _TRUE */
- if (chbw_allow == _FALSE) {
- u_ch = cur_ch;
- u_bw = cur_bw;
- u_offset = cur_ch_offset;
- for (i = 0; i < dvobj->iface_nums; i++) {
- iface = dvobj->padapters[i];
- mlme = &iface->mlmepriv;
- mlmeext = &iface->mlmeextpriv;
- if (!iface || iface == adapter)
- continue;
- if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface))
- && check_fwstate(mlme, WIFI_ASOC_STATE)
- ) {
- #ifdef CONFIG_SPCT_CH_SWITCH
- if (1)
- rtw_ap_inform_ch_switch(iface, pmlmeext->cur_channel , pmlmeext->cur_ch_offset);
- else
- #endif
- rtw_sta_flush(iface, _FALSE);
- rtw_hal_set_hwreg(iface, HW_VAR_CHECK_TXBUF, 0);
- set_fwstate(mlme, WIFI_OP_CH_SWITCHING);
- } else if (check_fwstate(mlme, WIFI_STATION_STATE)
- && check_fwstate(mlme, WIFI_ASOC_STATE)
- ) {
- rtw_disassoc_cmd(iface, 500, RTW_CMDF_DIRECTLY);
- rtw_indicate_disconnect(iface, 0, _FALSE);
- rtw_free_assoc_resources(iface, _TRUE);
- }
- }
- }
- #ifdef CONFIG_DFS_MASTER
- rtw_dfs_rd_en_decision(adapter, MLME_STA_CONNECTING, 0);
- #endif
- }
- #endif /* CONFIG_CONCURRENT_MODE */
- exit:
- if (connect_allow == _TRUE) {
- RTW_INFO(FUNC_ADPT_FMT" union: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
- *ch = u_ch;
- *bw = u_bw;
- *offset = u_offset;
- }
- return connect_allow == _TRUE ? _SUCCESS : _FAIL;
- }
- u8 rtw_set_chbw_hdl(_adapter *padapter, u8 *pbuf)
- {
- struct set_ch_parm *set_ch_parm;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
- set_ch_parm = (struct set_ch_parm *)pbuf;
- RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
- FUNC_NDEV_ARG(padapter->pnetdev),
- set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
- pmlmeext->cur_channel = set_ch_parm->ch;
- pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
- pmlmeext->cur_bwmode = set_ch_parm->bw;
- set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
- return H2C_SUCCESS;
- }
- u8 set_chplan_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- struct SetChannelPlan_param *setChannelPlan_param;
- struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
- setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
- if (!rtw_is_channel_plan_valid(setChannelPlan_param->channel_plan))
- return H2C_PARAMETERS_ERROR;
- rfctl->country_ent = setChannelPlan_param->country_ent;
- rfctl->ChannelPlan = setChannelPlan_param->channel_plan;
- rfctl->max_chan_nums = init_channel_set(padapter, rfctl->ChannelPlan, rfctl->channel_set);
- init_channel_list(padapter, rfctl->channel_set, &rfctl->channel_list);
- #ifdef CONFIG_TXPWR_LIMIT
- rtw_txpwr_init_regd(rfctl);
- #endif
- rtw_hal_set_odm_var(padapter, HAL_ODM_REGULATION, NULL, _TRUE);
- #ifdef CONFIG_IOCTL_CFG80211
- rtw_regd_apply_flags(adapter_to_wiphy(padapter));
- #endif
- return H2C_SUCCESS;
- }
- u8 led_blink_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- struct LedBlink_param *ledBlink_param;
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
- ledBlink_param = (struct LedBlink_param *)pbuf;
- #ifdef CONFIG_RTW_LED_HANDLED_BY_CMD_THREAD
- BlinkHandler((PLED_DATA)ledBlink_param->pLed);
- #endif
- return H2C_SUCCESS;
- }
- u8 set_csa_hdl(_adapter *adapter, unsigned char *pbuf)
- {
- #ifdef CONFIG_DFS
- struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
- if (rfctl->csa_ch)
- rtw_dfs_ch_switch_hdl(adapter_to_dvobj(adapter));
- #endif
- return H2C_SUCCESS;
- }
- u8 tdls_hdl(_adapter *padapter, unsigned char *pbuf)
- {
- #ifdef CONFIG_TDLS
- _irqL irqL;
- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
- struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
- #ifdef CONFIG_TDLS_CH_SW
- struct tdls_ch_switch *pchsw_info = &ptdlsinfo->chsw_info;
- #endif
- struct TDLSoption_param *TDLSoption;
- struct sta_info *ptdls_sta = NULL;
- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
- struct sta_info *ap_sta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(&(pmlmeinfo->network)));
- u8 survey_channel, i, min, option;
- struct tdls_txmgmt txmgmt;
- u32 setchtime, resp_sleep = 0, wait_time;
- u8 zaddr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- u8 ret;
- u8 doiqk;
- u64 tx_ra_bitmap = 0;
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
- TDLSoption = (struct TDLSoption_param *)pbuf;
- option = TDLSoption->option;
- if (!_rtw_memcmp(TDLSoption->addr, zaddr, ETH_ALEN)) {
- ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), TDLSoption->addr);
- if (ptdls_sta == NULL)
- return H2C_REJECTED;
- } else {
- if (!(option == TDLS_RS_RCR))
- return H2C_REJECTED;
- }
- /* _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); */
- /* RTW_INFO("[%s] option:%d\n", __FUNCTION__, option); */
- switch (option) {
- case TDLS_ESTABLISHED: {
- /* As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0 */
- /* So we can receive all kinds of data frames. */
- u8 sta_band = 0;
- /* leave ALL PS when TDLS is established */
- rtw_pwr_wakeup(padapter);
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_TDLS_LINKED);
- RTW_INFO("Created Direct Link with "MAC_FMT"\n", MAC_ARG(ptdls_sta->cmn.mac_addr));
- /* Set TDLS sta rate. */
- /* Update station supportRate */
- rtw_hal_update_sta_ra_info(padapter, ptdls_sta);
- tx_ra_bitmap = ptdls_sta->cmn.ra_info.ramask;
- if (pmlmeext->cur_channel > 14) {
- if (tx_ra_bitmap & 0xffff000)
- sta_band |= WIRELESS_11_5N ;
- if (tx_ra_bitmap & 0xff0)
- sta_band |= WIRELESS_11A;
- /* 5G band */
- #ifdef CONFIG_80211AC_VHT
- if (ptdls_sta->vhtpriv.vht_option)
- sta_band = WIRELESS_11_5AC;
- #endif
- } else {
- if (tx_ra_bitmap & 0xffff000)
- sta_band |= WIRELESS_11_24N;
- if (tx_ra_bitmap & 0xff0)
- sta_band |= WIRELESS_11G;
- if (tx_ra_bitmap & 0x0f)
- sta_band |= WIRELESS_11B;
- }
- ptdls_sta->wireless_mode = sta_band;
- rtw_hal_update_sta_wset(padapter, ptdls_sta);
- /* Sta mode */
- rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, ptdls_sta, _TRUE);
- set_sta_rate(padapter, ptdls_sta);
- rtw_sta_media_status_rpt(padapter, ptdls_sta, 1);
- break;
- }
- case TDLS_ISSUE_PTI:
- ptdls_sta->tdls_sta_state |= TDLS_WAIT_PTR_STATE;
- issue_tdls_peer_traffic_indication(padapter, ptdls_sta);
- _set_timer(&ptdls_sta->pti_timer, TDLS_PTI_TIME);
- break;
- #ifdef CONFIG_TDLS_CH_SW
- case TDLS_CH_SW_RESP:
- _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
- txmgmt.status_code = 0;
- _rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);
- if (ap_sta)
- rtw_hal_macid_sleep(padapter, ap_sta->cmn.mac_id);
- issue_nulldata(padapter, NULL, 1, 3, 3);
- RTW_INFO("[TDLS ] issue tdls channel switch response\n");
- ret = issue_tdls_ch_switch_rsp(padapter, &txmgmt, _TRUE);
- /* If we receive TDLS_CH_SW_REQ at off channel which it's target is AP's channel */
- /* then we just switch to AP's channel*/
- if (padapter->mlmeextpriv.cur_channel == pchsw_info->off_ch_num) {
- rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_END_TO_BASE_CHNL);
- break;
- }
- if (ret == _SUCCESS)
- rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_OFF_CHNL);
- else
- RTW_INFO("[TDLS] issue_tdls_ch_switch_rsp wait ack fail !!!!!!!!!!\n");
- break;
- case TDLS_CH_SW_PREPARE:
- pchsw_info->ch_sw_state |= TDLS_CH_SWITCH_PREPARE_STATE;
- /* to collect IQK info of off-chnl */
- doiqk = _TRUE;
- rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);
- set_channel_bwmode(padapter, pchsw_info->off_ch_num, pchsw_info->ch_offset, (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20);
- doiqk = _FALSE;
- rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);
- /* switch back to base-chnl */
- set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
- rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_START);
- pchsw_info->ch_sw_state &= ~(TDLS_CH_SWITCH_PREPARE_STATE);
- break;
- case TDLS_CH_SW_START:
- rtw_tdls_set_ch_sw_oper_control(padapter, _TRUE);
- break;
- case TDLS_CH_SW_TO_OFF_CHNL:
- if (ap_sta)
- rtw_hal_macid_sleep(padapter, ap_sta->cmn.mac_id);
- issue_nulldata(padapter, NULL, 1, 3, 3);
- if (padapter->registrypriv.wifi_spec == 0) {
- if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))
- _set_timer(&ptdls_sta->ch_sw_timer, (u32)(ptdls_sta->ch_switch_timeout) / 1000);
- }
- if (rtw_tdls_do_ch_sw(padapter, ptdls_sta, TDLS_CH_SW_OFF_CHNL, pchsw_info->off_ch_num,
- pchsw_info->ch_offset, (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20, ptdls_sta->ch_switch_time) == _SUCCESS) {
- pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE);
- if (pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) {
- if (issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta->cmn.mac_addr, 0, 1,
- (padapter->registrypriv.wifi_spec == 0) ? 3 : 0) == _FAIL)
- rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_BASE_CHNL);
- }
- } else {
- if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))
- _cancel_timer_ex(&ptdls_sta->ch_sw_timer);
- }
- break;
- case TDLS_CH_SW_END:
- case TDLS_CH_SW_END_TO_BASE_CHNL:
- rtw_tdls_set_ch_sw_oper_control(padapter, _FALSE);
- _cancel_timer_ex(&ptdls_sta->ch_sw_timer);
- _cancel_timer_ex(&ptdls_sta->stay_on_base_chnl_timer);
- _cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer);
- #if 0
- _rtw_memset(pHalData->tdls_ch_sw_iqk_info_base_chnl, 0x00, sizeof(pHalData->tdls_ch_sw_iqk_info_base_chnl));
- _rtw_memset(pHalData->tdls_ch_sw_iqk_info_off_chnl, 0x00, sizeof(pHalData->tdls_ch_sw_iqk_info_off_chnl));
- #endif
- if (option == TDLS_CH_SW_END_TO_BASE_CHNL)
- rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_BASE_CHNL);
- break;
- case TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED:
- case TDLS_CH_SW_TO_BASE_CHNL:
- pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE | TDLS_WAIT_CH_RSP_STATE);
- if (option == TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED) {
- if (ptdls_sta != NULL) {
- /* Send unsolicited channel switch rsp. to peer */
- _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
- txmgmt.status_code = 0;
- _rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);
- issue_tdls_ch_switch_rsp(padapter, &txmgmt, _FALSE);
- }
- }
- if (rtw_tdls_do_ch_sw(padapter, ptdls_sta, TDLS_CH_SW_BASE_CHNL, pmlmeext->cur_channel,
- pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode, ptdls_sta->ch_switch_time) == _SUCCESS) {
- if (ap_sta)
- rtw_hal_macid_wakeup(padapter, ap_sta->cmn.mac_id);
- issue_nulldata(padapter, NULL, 0, 3, 3);
- /* set ch sw monitor timer for responder */
- if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))
- _set_timer(&ptdls_sta->ch_sw_monitor_timer, TDLS_CH_SW_MONITOR_TIMEOUT);
- }
- break;
- #endif
- case TDLS_RS_RCR:
- rtw_hal_rcr_set_chk_bssid(padapter, MLME_TDLS_NOLINK);
- break;
- case TDLS_TEARDOWN_STA:
- case TDLS_TEARDOWN_STA_NO_WAIT:
- _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
- txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
- _rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);
- issue_tdls_teardown(padapter, &txmgmt, (option == TDLS_TEARDOWN_STA) ? _TRUE : _FALSE);
- break;
- case TDLS_TEARDOWN_STA_LOCALLY:
- case TDLS_TEARDOWN_STA_LOCALLY_POST:
- #ifdef CONFIG_TDLS_CH_SW
- if (_rtw_memcmp(TDLSoption->addr, pchsw_info->addr, ETH_ALEN) == _TRUE) {
- pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE |
- TDLS_CH_SWITCH_ON_STATE |
- TDLS_PEER_AT_OFF_STATE);
- rtw_tdls_set_ch_sw_oper_control(padapter, _FALSE);
- _rtw_memset(pchsw_info->addr, 0x00, ETH_ALEN);
- }
- #endif
- if (option == TDLS_TEARDOWN_STA_LOCALLY)
- rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);
- rtw_tdls_teardown_post_hdl(padapter, ptdls_sta, _FALSE);
- if (ptdlsinfo->tdls_sctx != NULL)
- rtw_sctx_done(&(ptdlsinfo->tdls_sctx));
- break;
- }
- /* _exit_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); */
- return H2C_SUCCESS;
- #else
- return H2C_REJECTED;
- #endif /* CONFIG_TDLS */
- }
- u8 run_in_thread_hdl(_adapter *padapter, u8 *pbuf)
- {
- struct RunInThread_param *p;
- if (NULL == pbuf)
- return H2C_PARAMETERS_ERROR;
- p = (struct RunInThread_param *)pbuf;
- if (p->func)
- p->func(p->context);
- return H2C_SUCCESS;
- }
- u8 rtw_getmacreg_hdl(_adapter *padapter, u8 *pbuf)
- {
- struct readMAC_parm *preadmacparm = NULL;
- u8 sz = 0;
- u32 addr = 0;
- u32 value = 0;
- if (!pbuf)
- return H2C_PARAMETERS_ERROR;
- preadmacparm = (struct readMAC_parm *) pbuf;
- sz = preadmacparm->len;
- addr = preadmacparm->addr;
- value = 0;
- switch (sz) {
- case 1:
- value = rtw_read8(padapter, addr);
- break;
- case 2:
- value = rtw_read16(padapter, addr);
- break;
- case 4:
- value = rtw_read32(padapter, addr);
- break;
- default:
- RTW_INFO("%s: Unknown size\n", __func__);
- break;
- }
- RTW_INFO("%s: addr:0x%02x valeu:0x%02x\n", __func__, addr, value);
- return H2C_SUCCESS;
- }
|