| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488 |
- /******************************************************************************
- *
- * 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;
- __attribute__ ((fallthrough));
- 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;
- __attribute__ ((fallthrough));
- 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;
- }
|