btmgmt.c 136 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * BlueZ - Bluetooth protocol stack for Linux
  4. *
  5. * Copyright (C) 2011 Intel Corporation. All rights reserved.
  6. *
  7. */
  8. #ifdef HAVE_CONFIG_H
  9. #include <config.h>
  10. #endif
  11. #define _GNU_SOURCE
  12. #include <stdio.h>
  13. #include <stdarg.h>
  14. #include <errno.h>
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/param.h>
  20. #include <sys/socket.h>
  21. #include <sys/stat.h>
  22. #include <fcntl.h>
  23. #include <poll.h>
  24. #include <getopt.h>
  25. #include <stdbool.h>
  26. #include <wordexp.h>
  27. #include <ctype.h>
  28. #include "lib/bluetooth.h"
  29. #include "lib/hci.h"
  30. #include "lib/hci_lib.h"
  31. #include "lib/sdp.h"
  32. #include "lib/sdp_lib.h"
  33. #include "src/uuid-helper.h"
  34. #include "lib/mgmt.h"
  35. #include "src/shared/mainloop.h"
  36. #include "src/shared/io.h"
  37. #include "src/shared/util.h"
  38. #include "src/shared/mgmt.h"
  39. #include "src/shared/shell.h"
  40. #define SCAN_TYPE_BREDR (1 << BDADDR_BREDR)
  41. #define SCAN_TYPE_LE ((1 << BDADDR_LE_PUBLIC) | (1 << BDADDR_LE_RANDOM))
  42. #define SCAN_TYPE_DUAL (SCAN_TYPE_BREDR | SCAN_TYPE_LE)
  43. static struct mgmt *mgmt = NULL;
  44. static uint16_t mgmt_index = MGMT_INDEX_NONE;
  45. static bool discovery = false;
  46. static bool resolve_names = true;
  47. static struct {
  48. uint16_t index;
  49. uint16_t req;
  50. struct mgmt_addr_info addr;
  51. } prompt = {
  52. .index = MGMT_INDEX_NONE,
  53. };
  54. static int pending_index = 0;
  55. #ifndef MIN
  56. #define MIN(x, y) ((x) < (y) ? (x) : (y))
  57. #endif
  58. #define PROMPT_ON COLOR_BLUE "[mgmt]" COLOR_OFF "# "
  59. static void set_index(const char *arg)
  60. {
  61. if (!arg || !strcmp(arg, "none") || !strcmp(arg, "any") ||
  62. !strcmp(arg, "all"))
  63. mgmt_index = MGMT_INDEX_NONE;
  64. else if(strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
  65. mgmt_index = atoi(&arg[3]);
  66. else
  67. mgmt_index = atoi(arg);
  68. }
  69. static bool parse_setting(int argc, char **argv, uint8_t *val)
  70. {
  71. if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
  72. *val = 1;
  73. else if (strcasecmp(argv[1], "off") == 0)
  74. *val = 0;
  75. else
  76. *val = atoi(argv[1]);
  77. return true;
  78. }
  79. static void update_prompt(uint16_t index)
  80. {
  81. char str[32];
  82. if (index == MGMT_INDEX_NONE)
  83. snprintf(str, sizeof(str), "%s# ",
  84. COLOR_BLUE "[mgmt]" COLOR_OFF);
  85. else
  86. snprintf(str, sizeof(str),
  87. COLOR_BLUE "[hci%u]" COLOR_OFF "# ", index);
  88. bt_shell_set_prompt(str);
  89. }
  90. #define print(fmt, arg...) do { \
  91. bt_shell_printf(fmt "\n", ## arg); \
  92. } while (0)
  93. #define error(fmt, arg...) do { \
  94. bt_shell_printf(COLOR_RED fmt "\n" COLOR_OFF, ## arg); \
  95. } while (0)
  96. static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen)
  97. {
  98. size_t i, len;
  99. len = MIN((strlen(hexstr) / 2), buflen);
  100. memset(buf, 0, len);
  101. for (i = 0; i < len; i++)
  102. sscanf(hexstr + (i * 2), "%02hhX", &buf[i]);
  103. return len;
  104. }
  105. static size_t bin2hex(const uint8_t *buf, size_t buflen, char *str,
  106. size_t strlen)
  107. {
  108. size_t i;
  109. for (i = 0; i < buflen && i < (strlen / 2); i++)
  110. sprintf(str + (i * 2), "%02x", buf[i]);
  111. return i;
  112. }
  113. static void print_eir(const uint8_t *eir, uint16_t eir_len)
  114. {
  115. uint16_t parsed = 0;
  116. char str[33];
  117. while (parsed < eir_len - 1) {
  118. uint8_t field_len = eir[0];
  119. if (field_len == 0)
  120. break;
  121. parsed += field_len + 1;
  122. if (parsed > eir_len)
  123. break;
  124. switch (eir[1]) {
  125. case 0x01:
  126. print("Flags: 0x%02x", eir[2]);
  127. break;
  128. case 0x0d:
  129. print("Class of Device: 0x%02x%02x%02x",
  130. eir[4], eir[3], eir[2]);
  131. break;
  132. case 0x0e:
  133. bin2hex(eir + 2, 16, str, sizeof(str));
  134. print("SSP Hash C-192: %s", str);
  135. break;
  136. case 0x0f:
  137. bin2hex(eir + 2, 16, str, sizeof(str));
  138. print("SSP Rand R-192: %s", str);
  139. break;
  140. case 0x1b:
  141. ba2str((bdaddr_t *) (eir + 2), str);
  142. print("LE Device Address: %s (%s)", str,
  143. eir[8] ? "random" : "public");
  144. break;
  145. case 0x1c:
  146. print("LE Role: 0x%02x", eir[2]);
  147. break;
  148. case 0x1d:
  149. bin2hex(eir + 2, 16, str, sizeof(str));
  150. print("SSP Hash C-256: %s", str);
  151. break;
  152. case 0x1e:
  153. bin2hex(eir + 2, 16, str, sizeof(str));
  154. print("SSP Rand R-256: %s", str);
  155. break;
  156. case 0x22:
  157. bin2hex(eir + 2, 16, str, sizeof(str));
  158. print("LE SC Confirmation Value: %s", str);
  159. break;
  160. case 0x23:
  161. bin2hex(eir + 2, 16, str, sizeof(str));
  162. print("LE SC Random Value: %s", str);
  163. break;
  164. default:
  165. print("Type %u: %u byte%s", eir[1], field_len - 1,
  166. (field_len - 1) == 1 ? "" : "s");
  167. break;
  168. }
  169. eir += field_len + 1;
  170. }
  171. }
  172. static bool load_identity(const char *path, struct mgmt_irk_info *irk)
  173. {
  174. char *addr, *key;
  175. unsigned int type;
  176. int n;
  177. FILE *fp;
  178. fp = fopen(path, "r");
  179. if (!fp) {
  180. error("Failed to open identity file: %s", strerror(errno));
  181. return false;
  182. }
  183. n = fscanf(fp, "%m[0-9a-f:] (type %u) %m[0-9a-f]", &addr, &type, &key);
  184. fclose(fp);
  185. if (n != 3)
  186. return false;
  187. str2ba(addr, &irk->addr.bdaddr);
  188. hex2bin(key, irk->val, sizeof(irk->val));
  189. free(addr);
  190. free(key);
  191. switch (type) {
  192. case 0:
  193. irk->addr.type = BDADDR_LE_PUBLIC;
  194. break;
  195. case 1:
  196. irk->addr.type = BDADDR_LE_RANDOM;
  197. break;
  198. default:
  199. error("Invalid address type %u", type);
  200. return false;
  201. }
  202. return true;
  203. }
  204. static void controller_error(uint16_t index, uint16_t len,
  205. const void *param, void *user_data)
  206. {
  207. const struct mgmt_ev_controller_error *ev = param;
  208. if (len < sizeof(*ev)) {
  209. error("Too short (%u bytes) controller error event", len);
  210. return;
  211. }
  212. print("hci%u error 0x%02x", index, ev->error_code);
  213. }
  214. static void index_added(uint16_t index, uint16_t len,
  215. const void *param, void *user_data)
  216. {
  217. print("hci%u added", index);
  218. }
  219. static void index_removed(uint16_t index, uint16_t len,
  220. const void *param, void *user_data)
  221. {
  222. print("hci%u removed", index);
  223. }
  224. static void unconf_index_added(uint16_t index, uint16_t len,
  225. const void *param, void *user_data)
  226. {
  227. print("hci%u added (unconfigured)", index);
  228. }
  229. static void unconf_index_removed(uint16_t index, uint16_t len,
  230. const void *param, void *user_data)
  231. {
  232. print("hci%u removed (unconfigured)", index);
  233. }
  234. static void ext_index_added(uint16_t index, uint16_t len,
  235. const void *param, void *user_data)
  236. {
  237. const struct mgmt_ev_ext_index_added *ev = param;
  238. print("hci%u added (type %u bus %u)", index, ev->type, ev->bus);
  239. }
  240. static void ext_index_removed(uint16_t index, uint16_t len,
  241. const void *param, void *user_data)
  242. {
  243. const struct mgmt_ev_ext_index_removed *ev = param;
  244. print("hci%u removed (type %u bus %u)", index, ev->type, ev->bus);
  245. }
  246. static const char *options_str[] = {
  247. "external",
  248. "public-address",
  249. };
  250. static const char *options2str(uint32_t options)
  251. {
  252. static char str[256];
  253. unsigned i;
  254. int off;
  255. off = 0;
  256. str[0] = '\0';
  257. for (i = 0; i < NELEM(options_str); i++) {
  258. if ((options & (1 << i)) != 0)
  259. off += snprintf(str + off, sizeof(str) - off, "%s ",
  260. options_str[i]);
  261. }
  262. return str;
  263. }
  264. static void new_config_options(uint16_t index, uint16_t len,
  265. const void *param, void *user_data)
  266. {
  267. const uint32_t *ev = param;
  268. if (len < sizeof(*ev)) {
  269. error("Too short new_config_options event (%u)", len);
  270. return;
  271. }
  272. print("hci%u new_config_options: %s", index, options2str(get_le32(ev)));
  273. }
  274. static const char *settings_str[] = {
  275. "powered",
  276. "connectable",
  277. "fast-connectable",
  278. "discoverable",
  279. "bondable",
  280. "link-security",
  281. "ssp",
  282. "br/edr",
  283. "hs",
  284. "le",
  285. "advertising",
  286. "secure-conn",
  287. "debug-keys",
  288. "privacy",
  289. "configuration",
  290. "static-addr",
  291. "phy-configuration",
  292. "wide-band-speech",
  293. };
  294. static const char *settings2str(uint32_t settings)
  295. {
  296. static char str[256];
  297. unsigned i;
  298. int off;
  299. off = 0;
  300. str[0] = '\0';
  301. for (i = 0; i < NELEM(settings_str); i++) {
  302. if ((settings & (1 << i)) != 0)
  303. off += snprintf(str + off, sizeof(str) - off, "%s ",
  304. settings_str[i]);
  305. }
  306. return str;
  307. }
  308. static void new_settings(uint16_t index, uint16_t len,
  309. const void *param, void *user_data)
  310. {
  311. const uint32_t *ev = param;
  312. if (len < sizeof(*ev)) {
  313. error("Too short new_settings event (%u)", len);
  314. return;
  315. }
  316. print("hci%u new_settings: %s", index, settings2str(get_le32(ev)));
  317. }
  318. static void discovering(uint16_t index, uint16_t len, const void *param,
  319. void *user_data)
  320. {
  321. const struct mgmt_ev_discovering *ev = param;
  322. if (len < sizeof(*ev)) {
  323. error("Too short (%u bytes) discovering event", len);
  324. return;
  325. }
  326. print("hci%u type %u discovering %s", index, ev->type,
  327. ev->discovering ? "on" : "off");
  328. if (ev->discovering == 0 && discovery)
  329. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  330. }
  331. static void new_link_key(uint16_t index, uint16_t len, const void *param,
  332. void *user_data)
  333. {
  334. const struct mgmt_ev_new_link_key *ev = param;
  335. char addr[18];
  336. if (len != sizeof(*ev)) {
  337. error("Invalid new_link_key length (%u bytes)", len);
  338. return;
  339. }
  340. ba2str(&ev->key.addr.bdaddr, addr);
  341. print("hci%u new_link_key %s type 0x%02x pin_len %d store_hint %u",
  342. index, addr, ev->key.type, ev->key.pin_len, ev->store_hint);
  343. }
  344. static const char *typestr(uint8_t type)
  345. {
  346. static const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
  347. if (type <= BDADDR_LE_RANDOM)
  348. return str[type];
  349. return "(unknown)";
  350. }
  351. static void connected(uint16_t index, uint16_t len, const void *param,
  352. void *user_data)
  353. {
  354. const struct mgmt_ev_device_connected *ev = param;
  355. uint16_t eir_len;
  356. char addr[18];
  357. if (len < sizeof(*ev)) {
  358. error("Invalid connected event length (%u bytes)", len);
  359. return;
  360. }
  361. eir_len = get_le16(&ev->eir_len);
  362. if (len != sizeof(*ev) + eir_len) {
  363. error("Invalid connected event length (%u != eir_len %u)",
  364. len, eir_len);
  365. return;
  366. }
  367. ba2str(&ev->addr.bdaddr, addr);
  368. print("hci%u %s type %s connected eir_len %u", index, addr,
  369. typestr(ev->addr.type), eir_len);
  370. }
  371. static void disconnected(uint16_t index, uint16_t len, const void *param,
  372. void *user_data)
  373. {
  374. const struct mgmt_ev_device_disconnected *ev = param;
  375. char addr[18];
  376. uint8_t reason;
  377. if (len < sizeof(struct mgmt_addr_info)) {
  378. error("Invalid disconnected event length (%u bytes)", len);
  379. return;
  380. }
  381. if (len < sizeof(*ev))
  382. reason = MGMT_DEV_DISCONN_UNKNOWN;
  383. else
  384. reason = ev->reason;
  385. ba2str(&ev->addr.bdaddr, addr);
  386. print("hci%u %s type %s disconnected with reason %u",
  387. index, addr, typestr(ev->addr.type), reason);
  388. }
  389. static void conn_failed(uint16_t index, uint16_t len, const void *param,
  390. void *user_data)
  391. {
  392. const struct mgmt_ev_connect_failed *ev = param;
  393. char addr[18];
  394. if (len != sizeof(*ev)) {
  395. error("Invalid connect_failed event length (%u bytes)", len);
  396. return;
  397. }
  398. ba2str(&ev->addr.bdaddr, addr);
  399. print("hci%u %s type %s connect failed (status 0x%02x, %s)",
  400. index, addr, typestr(ev->addr.type), ev->status,
  401. mgmt_errstr(ev->status));
  402. }
  403. static void auth_failed(uint16_t index, uint16_t len, const void *param,
  404. void *user_data)
  405. {
  406. const struct mgmt_ev_auth_failed *ev = param;
  407. char addr[18];
  408. if (len != sizeof(*ev)) {
  409. error("Invalid auth_failed event length (%u bytes)", len);
  410. return;
  411. }
  412. ba2str(&ev->addr.bdaddr, addr);
  413. print("hci%u %s auth failed with status 0x%02x (%s)",
  414. index, addr, ev->status, mgmt_errstr(ev->status));
  415. }
  416. static void class_of_dev_changed(uint16_t index, uint16_t len,
  417. const void *param, void *user_data)
  418. {
  419. const struct mgmt_ev_class_of_dev_changed *ev = param;
  420. if (len != sizeof(*ev)) {
  421. error("Invalid class_of_dev_changed length (%u bytes)", len);
  422. return;
  423. }
  424. print("hci%u class of device changed: 0x%02x%02x%02x", index,
  425. ev->dev_class[2], ev->dev_class[1], ev->dev_class[0]);
  426. }
  427. static void local_name_changed(uint16_t index, uint16_t len, const void *param,
  428. void *user_data)
  429. {
  430. const struct mgmt_ev_local_name_changed *ev = param;
  431. if (len != sizeof(*ev)) {
  432. error("Invalid local_name_changed length (%u bytes)", len);
  433. return;
  434. }
  435. print("hci%u name changed: %s", index, ev->name);
  436. }
  437. static void confirm_name_rsp(uint8_t status, uint16_t len,
  438. const void *param, void *user_data)
  439. {
  440. const struct mgmt_rp_confirm_name *rp = param;
  441. char addr[18];
  442. if (len == 0 && status != 0) {
  443. error("confirm_name failed with status 0x%02x (%s)", status,
  444. mgmt_errstr(status));
  445. return;
  446. }
  447. if (len != sizeof(*rp)) {
  448. error("confirm_name rsp length %u instead of %zu",
  449. len, sizeof(*rp));
  450. return;
  451. }
  452. ba2str(&rp->addr.bdaddr, addr);
  453. if (status != 0)
  454. error("confirm_name for %s failed: 0x%02x (%s)",
  455. addr, status, mgmt_errstr(status));
  456. else
  457. print("confirm_name succeeded for %s", addr);
  458. }
  459. static char *eir_get_name(const uint8_t *eir, uint16_t eir_len)
  460. {
  461. uint8_t parsed = 0;
  462. if (eir_len < 2)
  463. return NULL;
  464. while (parsed < eir_len - 1) {
  465. uint8_t field_len = eir[0];
  466. if (field_len == 0)
  467. break;
  468. parsed += field_len + 1;
  469. if (parsed > eir_len)
  470. break;
  471. /* Check for short of complete name */
  472. if (eir[1] == 0x09 || eir[1] == 0x08)
  473. return strndup((char *) &eir[2], field_len - 1);
  474. eir += field_len + 1;
  475. }
  476. return NULL;
  477. }
  478. static unsigned int eir_get_flags(const uint8_t *eir, uint16_t eir_len)
  479. {
  480. uint8_t parsed = 0;
  481. if (eir_len < 2)
  482. return 0;
  483. while (parsed < eir_len - 1) {
  484. uint8_t field_len = eir[0];
  485. if (field_len == 0)
  486. break;
  487. parsed += field_len + 1;
  488. if (parsed > eir_len)
  489. break;
  490. /* Check for flags */
  491. if (eir[1] == 0x01)
  492. return eir[2];
  493. eir += field_len + 1;
  494. }
  495. return 0;
  496. }
  497. static void device_found(uint16_t index, uint16_t len, const void *param,
  498. void *user_data)
  499. {
  500. const struct mgmt_ev_device_found *ev = param;
  501. struct mgmt *mgmt = user_data;
  502. uint16_t eir_len;
  503. uint32_t flags;
  504. if (len < sizeof(*ev)) {
  505. error("Too short device_found length (%u bytes)", len);
  506. return;
  507. }
  508. flags = btohl(ev->flags);
  509. eir_len = get_le16(&ev->eir_len);
  510. if (len != sizeof(*ev) + eir_len) {
  511. error("dev_found: expected %zu bytes, got %u bytes",
  512. sizeof(*ev) + eir_len, len);
  513. return;
  514. }
  515. if (discovery) {
  516. char addr[18], *name;
  517. ba2str(&ev->addr.bdaddr, addr);
  518. print("hci%u dev_found: %s type %s rssi %d "
  519. "flags 0x%04x ", index, addr,
  520. typestr(ev->addr.type), ev->rssi, flags);
  521. if (ev->addr.type != BDADDR_BREDR)
  522. print("AD flags 0x%02x ",
  523. eir_get_flags(ev->eir, eir_len));
  524. name = eir_get_name(ev->eir, eir_len);
  525. if (name)
  526. print("name %s", name);
  527. else
  528. print("eir_len %u", eir_len);
  529. free(name);
  530. }
  531. if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
  532. struct mgmt_cp_confirm_name cp;
  533. memset(&cp, 0, sizeof(cp));
  534. memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
  535. if (resolve_names)
  536. cp.name_known = 0;
  537. else
  538. cp.name_known = 1;
  539. mgmt_reply(mgmt, MGMT_OP_CONFIRM_NAME, index, sizeof(cp), &cp,
  540. confirm_name_rsp, NULL, NULL);
  541. }
  542. }
  543. static void pin_rsp(uint8_t status, uint16_t len, const void *param,
  544. void *user_data)
  545. {
  546. if (status != 0) {
  547. error("PIN Code reply failed with status 0x%02x (%s)",
  548. status, mgmt_errstr(status));
  549. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  550. }
  551. print("PIN Reply successful");
  552. }
  553. static int mgmt_pin_reply(uint16_t index, const struct mgmt_addr_info *addr,
  554. const char *pin, size_t len)
  555. {
  556. struct mgmt_cp_pin_code_reply cp;
  557. memset(&cp, 0, sizeof(cp));
  558. memcpy(&cp.addr, addr, sizeof(cp.addr));
  559. cp.pin_len = len;
  560. memcpy(cp.pin_code, pin, len);
  561. return mgmt_reply(mgmt, MGMT_OP_PIN_CODE_REPLY, index,
  562. sizeof(cp), &cp, pin_rsp, NULL, NULL);
  563. }
  564. static void pin_neg_rsp(uint8_t status, uint16_t len, const void *param,
  565. void *user_data)
  566. {
  567. if (status != 0) {
  568. error("PIN Neg reply failed with status 0x%02x (%s)",
  569. status, mgmt_errstr(status));
  570. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  571. }
  572. print("PIN Negative Reply successful");
  573. }
  574. static int mgmt_pin_neg_reply(uint16_t index, const struct mgmt_addr_info *addr)
  575. {
  576. struct mgmt_cp_pin_code_neg_reply cp;
  577. memset(&cp, 0, sizeof(cp));
  578. memcpy(&cp.addr, addr, sizeof(cp.addr));
  579. return mgmt_reply(mgmt, MGMT_OP_PIN_CODE_NEG_REPLY, index,
  580. sizeof(cp), &cp, pin_neg_rsp, NULL, NULL);
  581. }
  582. static void confirm_rsp(uint8_t status, uint16_t len, const void *param,
  583. void *user_data)
  584. {
  585. if (status != 0) {
  586. error("User Confirm reply failed. status 0x%02x (%s)",
  587. status, mgmt_errstr(status));
  588. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  589. }
  590. print("User Confirm Reply successful");
  591. }
  592. static int mgmt_confirm_reply(uint16_t index, const struct mgmt_addr_info *addr)
  593. {
  594. struct mgmt_cp_user_confirm_reply cp;
  595. memset(&cp, 0, sizeof(cp));
  596. memcpy(&cp.addr, addr, sizeof(*addr));
  597. return mgmt_reply(mgmt, MGMT_OP_USER_CONFIRM_REPLY, index,
  598. sizeof(cp), &cp, confirm_rsp, NULL, NULL);
  599. }
  600. static void confirm_neg_rsp(uint8_t status, uint16_t len, const void *param,
  601. void *user_data)
  602. {
  603. if (status != 0) {
  604. error("Confirm Neg reply failed. status 0x%02x (%s)",
  605. status, mgmt_errstr(status));
  606. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  607. }
  608. print("User Confirm Negative Reply successful");
  609. }
  610. static int mgmt_confirm_neg_reply(uint16_t index,
  611. const struct mgmt_addr_info *addr)
  612. {
  613. struct mgmt_cp_user_confirm_reply cp;
  614. memset(&cp, 0, sizeof(cp));
  615. memcpy(&cp.addr, addr, sizeof(*addr));
  616. return mgmt_reply(mgmt, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
  617. sizeof(cp), &cp, confirm_neg_rsp, NULL, NULL);
  618. }
  619. static void passkey_rsp(uint8_t status, uint16_t len, const void *param,
  620. void *user_data)
  621. {
  622. if (status != 0) {
  623. error("User Passkey reply failed. status 0x%02x (%s)",
  624. status, mgmt_errstr(status));
  625. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  626. }
  627. print("User Passkey Reply successful");
  628. }
  629. static int mgmt_passkey_reply(uint16_t index, const struct mgmt_addr_info *addr,
  630. uint32_t passkey)
  631. {
  632. struct mgmt_cp_user_passkey_reply cp;
  633. memset(&cp, 0, sizeof(cp));
  634. memcpy(&cp.addr, addr, sizeof(*addr));
  635. put_le32(passkey, &cp.passkey);
  636. return mgmt_reply(mgmt, MGMT_OP_USER_PASSKEY_REPLY, index,
  637. sizeof(cp), &cp, passkey_rsp, NULL, NULL);
  638. }
  639. static void passkey_neg_rsp(uint8_t status, uint16_t len, const void *param,
  640. void *user_data)
  641. {
  642. if (status != 0) {
  643. error("Passkey Neg reply failed. status 0x%02x (%s)",
  644. status, mgmt_errstr(status));
  645. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  646. }
  647. print("User Passkey Negative Reply successful");
  648. }
  649. static int mgmt_passkey_neg_reply(uint16_t index,
  650. const struct mgmt_addr_info *addr)
  651. {
  652. struct mgmt_cp_user_passkey_reply cp;
  653. memset(&cp, 0, sizeof(cp));
  654. memcpy(&cp.addr, addr, sizeof(*addr));
  655. return mgmt_reply(mgmt, MGMT_OP_USER_PASSKEY_NEG_REPLY, index,
  656. sizeof(cp), &cp, passkey_neg_rsp, NULL, NULL);
  657. }
  658. static void prompt_input(const char *input, void *user_data)
  659. {
  660. size_t len;
  661. len = strlen(input);
  662. switch (prompt.req) {
  663. case MGMT_EV_PIN_CODE_REQUEST:
  664. if (len)
  665. mgmt_pin_reply(prompt.index, &prompt.addr, input, len);
  666. else
  667. mgmt_pin_neg_reply(prompt.index, &prompt.addr);
  668. break;
  669. case MGMT_EV_USER_PASSKEY_REQUEST:
  670. if (strlen(input) > 0)
  671. mgmt_passkey_reply(prompt.index, &prompt.addr,
  672. atoi(input));
  673. else
  674. mgmt_passkey_neg_reply(prompt.index,
  675. &prompt.addr);
  676. break;
  677. case MGMT_EV_USER_CONFIRM_REQUEST:
  678. if (input[0] == 'y' || input[0] == 'Y')
  679. mgmt_confirm_reply(prompt.index, &prompt.addr);
  680. else
  681. mgmt_confirm_neg_reply(prompt.index, &prompt.addr);
  682. break;
  683. }
  684. }
  685. static void ask(uint16_t index, uint16_t req, const struct mgmt_addr_info *addr,
  686. const char *fmt, ...)
  687. {
  688. char msg[256];
  689. va_list ap;
  690. int off;
  691. prompt.index = index;
  692. prompt.req = req;
  693. memcpy(&prompt.addr, addr, sizeof(*addr));
  694. va_start(ap, fmt);
  695. off = vsnprintf(msg, sizeof(msg), fmt, ap);
  696. va_end(ap);
  697. snprintf(msg + off, sizeof(msg) - off, " %s ",
  698. COLOR_BOLDGRAY ">>" COLOR_OFF);
  699. bt_shell_prompt_input("", msg, prompt_input, NULL);
  700. }
  701. static void request_pin(uint16_t index, uint16_t len, const void *param,
  702. void *user_data)
  703. {
  704. const struct mgmt_ev_pin_code_request *ev = param;
  705. char addr[18];
  706. if (len != sizeof(*ev)) {
  707. error("Invalid pin_code request length (%u bytes)", len);
  708. return;
  709. }
  710. ba2str(&ev->addr.bdaddr, addr);
  711. print("hci%u %s request PIN", index, addr);
  712. ask(index, MGMT_EV_PIN_CODE_REQUEST, &ev->addr,
  713. "PIN Request (press enter to reject)");
  714. }
  715. static void user_confirm(uint16_t index, uint16_t len, const void *param,
  716. void *user_data)
  717. {
  718. const struct mgmt_ev_user_confirm_request *ev = param;
  719. uint32_t val;
  720. char addr[18];
  721. if (len != sizeof(*ev)) {
  722. error("Invalid user_confirm request length (%u)", len);
  723. return;
  724. }
  725. ba2str(&ev->addr.bdaddr, addr);
  726. val = get_le32(&ev->value);
  727. print("hci%u %s User Confirm %06u hint %u", index, addr,
  728. val, ev->confirm_hint);
  729. if (ev->confirm_hint)
  730. ask(index, MGMT_EV_USER_CONFIRM_REQUEST, &ev->addr,
  731. "Accept pairing with %s (yes/no)", addr);
  732. else
  733. ask(index, MGMT_EV_USER_CONFIRM_REQUEST, &ev->addr,
  734. "Confirm value %06u for %s (yes/no)", val, addr);
  735. }
  736. static void request_passkey(uint16_t index, uint16_t len, const void *param,
  737. void *user_data)
  738. {
  739. const struct mgmt_ev_user_passkey_request *ev = param;
  740. char addr[18];
  741. if (len != sizeof(*ev)) {
  742. error("Invalid passkey request length (%u bytes)", len);
  743. return;
  744. }
  745. ba2str(&ev->addr.bdaddr, addr);
  746. print("hci%u %s request passkey", index, addr);
  747. ask(index, MGMT_EV_USER_PASSKEY_REQUEST, &ev->addr,
  748. "Passkey Request (press enter to reject)");
  749. }
  750. static void passkey_notify(uint16_t index, uint16_t len, const void *param,
  751. void *user_data)
  752. {
  753. const struct mgmt_ev_passkey_notify *ev = param;
  754. char addr[18];
  755. if (len != sizeof(*ev)) {
  756. error("Invalid passkey request length (%u bytes)", len);
  757. return;
  758. }
  759. ba2str(&ev->addr.bdaddr, addr);
  760. print("hci%u %s request passkey", index, addr);
  761. print("Passkey Notify: %06u (entered %u)", get_le32(&ev->passkey),
  762. ev->entered);
  763. }
  764. static void local_oob_data_updated(uint16_t index, uint16_t len,
  765. const void *param, void *user_data)
  766. {
  767. const struct mgmt_ev_local_oob_data_updated *ev = param;
  768. uint16_t eir_len;
  769. if (len < sizeof(*ev)) {
  770. error("Too small (%u bytes) local_oob_updated event", len);
  771. return;
  772. }
  773. eir_len = le16_to_cpu(ev->eir_len);
  774. if (len != sizeof(*ev) + eir_len) {
  775. error("local_oob_updated: expected %zu bytes, got %u bytes",
  776. sizeof(*ev) + eir_len, len);
  777. return;
  778. }
  779. print("hci%u oob data updated: type %u len %u", index,
  780. ev->type, eir_len);
  781. }
  782. static void advertising_added(uint16_t index, uint16_t len,
  783. const void *param, void *user_data)
  784. {
  785. const struct mgmt_ev_advertising_added *ev = param;
  786. if (len < sizeof(*ev)) {
  787. error("Too small (%u bytes) advertising_added event", len);
  788. return;
  789. }
  790. print("hci%u advertising_added: instance %u", index, ev->instance);
  791. }
  792. static void advertising_removed(uint16_t index, uint16_t len,
  793. const void *param, void *user_data)
  794. {
  795. const struct mgmt_ev_advertising_removed *ev = param;
  796. if (len < sizeof(*ev)) {
  797. error("Too small (%u bytes) advertising_removed event", len);
  798. return;
  799. }
  800. print("hci%u advertising_removed: instance %u", index, ev->instance);
  801. }
  802. static void flags_changed(uint16_t index, uint16_t len, const void *param,
  803. void *user_data)
  804. {
  805. const struct mgmt_ev_device_flags_changed *ev = param;
  806. char addr[18];
  807. if (len < sizeof(*ev)) {
  808. error("Too small (%u bytes) %s event", len, __func__);
  809. return;
  810. }
  811. ba2str(&ev->addr.bdaddr, addr);
  812. print("hci%u device_flags_changed: %s (%s)", index, addr,
  813. typestr(ev->addr.type));
  814. print(" supp: 0x%08x curr: 0x%08x",
  815. ev->supported_flags, ev->current_flags);
  816. }
  817. static void advmon_added(uint16_t index, uint16_t len, const void *param,
  818. void *user_data)
  819. {
  820. const struct mgmt_ev_adv_monitor_added *ev = param;
  821. if (len < sizeof(*ev)) {
  822. error("Too small (%u bytes) %s event", len, __func__);
  823. return;
  824. }
  825. print("hci%u %s: handle %u", index, __func__,
  826. le16_to_cpu(ev->monitor_handle));
  827. }
  828. static void advmon_removed(uint16_t index, uint16_t len, const void *param,
  829. void *user_data)
  830. {
  831. const struct mgmt_ev_adv_monitor_removed *ev = param;
  832. if (len < sizeof(*ev)) {
  833. error("Too small (%u bytes) %s event", len, __func__);
  834. return;
  835. }
  836. print("hci%u %s: handle %u", index, __func__,
  837. le16_to_cpu(ev->monitor_handle));
  838. }
  839. static void version_rsp(uint8_t status, uint16_t len, const void *param,
  840. void *user_data)
  841. {
  842. const struct mgmt_rp_read_version *rp = param;
  843. if (status != 0) {
  844. error("Reading mgmt version failed with status 0x%02x (%s)",
  845. status, mgmt_errstr(status));
  846. goto done;
  847. }
  848. if (len < sizeof(*rp)) {
  849. error("Too small version reply (%u bytes)", len);
  850. goto done;
  851. }
  852. print("MGMT Version %u, revision %u", rp->version,
  853. get_le16(&rp->revision));
  854. done:
  855. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  856. }
  857. static void cmd_revision(int argc, char **argv)
  858. {
  859. if (mgmt_send(mgmt, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
  860. 0, NULL, version_rsp, NULL, NULL) == 0) {
  861. error("Unable to send read_version cmd");
  862. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  863. }
  864. }
  865. static void commands_rsp(uint8_t status, uint16_t len, const void *param,
  866. void *user_data)
  867. {
  868. const struct mgmt_rp_read_commands *rp = param;
  869. uint16_t num_commands, num_events;
  870. size_t expected_len;
  871. int i;
  872. if (status != 0) {
  873. error("Read Supported Commands failed: status 0x%02x (%s)",
  874. status, mgmt_errstr(status));
  875. goto done;
  876. }
  877. if (len < sizeof(*rp)) {
  878. error("Too small commands reply (%u bytes)", len);
  879. goto done;
  880. }
  881. num_commands = get_le16(&rp->num_commands);
  882. num_events = get_le16(&rp->num_events);
  883. expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
  884. num_events * sizeof(uint16_t);
  885. if (len < expected_len) {
  886. error("Too small commands reply (%u != %zu)",
  887. len, expected_len);
  888. goto done;
  889. }
  890. print("%u commands:", num_commands);
  891. for (i = 0; i < num_commands; i++) {
  892. uint16_t op = get_le16(rp->opcodes + i);
  893. print("\t%s (0x%04x)", mgmt_opstr(op), op);
  894. }
  895. print("%u events:", num_events);
  896. for (i = 0; i < num_events; i++) {
  897. uint16_t ev = get_le16(rp->opcodes + num_commands + i);
  898. print("\t%s (0x%04x)", mgmt_evstr(ev), ev);
  899. }
  900. done:
  901. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  902. }
  903. static void cmd_commands(int argc,
  904. char **argv)
  905. {
  906. if (mgmt_send(mgmt, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
  907. 0, NULL, commands_rsp, NULL, NULL) == 0) {
  908. error("Unable to send read_commands cmd");
  909. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  910. }
  911. }
  912. static void config_info_rsp(uint8_t status, uint16_t len, const void *param,
  913. void *user_data)
  914. {
  915. const struct mgmt_rp_read_config_info *rp = param;
  916. uint16_t index = PTR_TO_UINT(user_data);
  917. uint32_t supported_options, missing_options;
  918. if (status != 0) {
  919. error("Reading hci%u config failed with status 0x%02x (%s)",
  920. index, status, mgmt_errstr(status));
  921. goto done;
  922. }
  923. if (len < sizeof(*rp)) {
  924. error("Too small info reply (%u bytes)", len);
  925. goto done;
  926. }
  927. print("hci%u:\tUnconfigured controller", index);
  928. print("\tmanufacturer %u", le16_to_cpu(rp->manufacturer));
  929. supported_options = le32_to_cpu(rp->supported_options);
  930. print("\tsupported options: %s", options2str(supported_options));
  931. missing_options = le32_to_cpu(rp->missing_options);
  932. print("\tmissing options: %s", options2str(missing_options));
  933. done:
  934. pending_index--;
  935. if (pending_index > 0)
  936. return;
  937. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  938. }
  939. static void unconf_index_rsp(uint8_t status, uint16_t len, const void *param,
  940. void *user_data)
  941. {
  942. const struct mgmt_rp_read_unconf_index_list *rp = param;
  943. uint16_t count;
  944. unsigned int i;
  945. if (status != 0) {
  946. error("Reading index list failed with status 0x%02x (%s)",
  947. status, mgmt_errstr(status));
  948. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  949. }
  950. if (len < sizeof(*rp)) {
  951. error("Too small index list reply (%u bytes)", len);
  952. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  953. }
  954. count = le16_to_cpu(rp->num_controllers);
  955. if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
  956. error("Index count (%u) doesn't match reply length (%u)",
  957. count, len);
  958. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  959. }
  960. print("Unconfigured index list with %u item%s",
  961. count, count != 1 ? "s" : "");
  962. for (i = 0; i < count; i++) {
  963. uint16_t index = le16_to_cpu(rp->index[i]);
  964. if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO, index, 0, NULL,
  965. config_info_rsp, UINT_TO_PTR(index), NULL)) {
  966. error("Unable to send read_config_info cmd");
  967. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  968. }
  969. pending_index++;
  970. }
  971. if (!count)
  972. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  973. }
  974. static void cmd_config(int argc, char **argv)
  975. {
  976. if (mgmt_index == MGMT_INDEX_NONE) {
  977. if (!mgmt_send(mgmt, MGMT_OP_READ_UNCONF_INDEX_LIST,
  978. MGMT_INDEX_NONE, 0, NULL,
  979. unconf_index_rsp, mgmt, NULL)) {
  980. error("Unable to send unconf_index_list cmd");
  981. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  982. }
  983. return;
  984. }
  985. if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO, mgmt_index, 0, NULL,
  986. config_info_rsp, UINT_TO_PTR(index), NULL)) {
  987. error("Unable to send read_config_info cmd");
  988. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  989. }
  990. }
  991. static void config_options_rsp(uint8_t status, uint16_t len, const void *param,
  992. void *user_data)
  993. {
  994. const struct mgmt_rp_read_config_info *rp = param;
  995. uint16_t index = PTR_TO_UINT(user_data);
  996. uint32_t supported_options, missing_options;
  997. if (status != 0) {
  998. error("Reading hci%u config failed with status 0x%02x (%s)",
  999. index, status, mgmt_errstr(status));
  1000. goto done;
  1001. }
  1002. if (len < sizeof(*rp)) {
  1003. error("Too small info reply (%u bytes)", len);
  1004. goto done;
  1005. }
  1006. print("hci%u:\tConfiguration options", index);
  1007. supported_options = le32_to_cpu(rp->supported_options);
  1008. print("\tsupported options: %s", options2str(supported_options));
  1009. missing_options = le32_to_cpu(rp->missing_options);
  1010. print("\tmissing options: %s", options2str(missing_options));
  1011. done:
  1012. pending_index--;
  1013. if (pending_index > 0)
  1014. return;
  1015. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1016. }
  1017. static void info_rsp(uint8_t status, uint16_t len, const void *param,
  1018. void *user_data)
  1019. {
  1020. const struct mgmt_rp_read_info *rp = param;
  1021. uint16_t index = PTR_TO_UINT(user_data);
  1022. uint32_t supported_settings, current_settings;
  1023. char addr[18];
  1024. if (status != 0) {
  1025. error("Reading hci%u info failed with status 0x%02x (%s)",
  1026. index, status, mgmt_errstr(status));
  1027. goto done;
  1028. }
  1029. if (len < sizeof(*rp)) {
  1030. error("Too small info reply (%u bytes)", len);
  1031. goto done;
  1032. }
  1033. print("hci%u:\tPrimary controller", index);
  1034. ba2str(&rp->bdaddr, addr);
  1035. print("\taddr %s version %u manufacturer %u class 0x%02x%02x%02x",
  1036. addr, rp->version, le16_to_cpu(rp->manufacturer),
  1037. rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
  1038. supported_settings = le32_to_cpu(rp->supported_settings);
  1039. print("\tsupported settings: %s", settings2str(supported_settings));
  1040. current_settings = le32_to_cpu(rp->current_settings);
  1041. print("\tcurrent settings: %s", settings2str(current_settings));
  1042. print("\tname %s", rp->name);
  1043. print("\tshort name %s", rp->short_name);
  1044. if (supported_settings & MGMT_SETTING_CONFIGURATION) {
  1045. if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
  1046. index, 0, NULL, config_options_rsp,
  1047. UINT_TO_PTR(index), NULL)) {
  1048. error("Unable to send read_config cmd");
  1049. goto done;
  1050. }
  1051. return;
  1052. }
  1053. done:
  1054. pending_index--;
  1055. if (pending_index > 0)
  1056. return;
  1057. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1058. }
  1059. static void ext_info_rsp(uint8_t status, uint16_t len, const void *param,
  1060. void *user_data)
  1061. {
  1062. const struct mgmt_rp_read_ext_info *rp = param;
  1063. uint16_t index = PTR_TO_UINT(user_data);
  1064. uint32_t supported_settings, current_settings;
  1065. char addr[18];
  1066. if (status != 0) {
  1067. error("Reading hci%u info failed with status 0x%02x (%s)",
  1068. index, status, mgmt_errstr(status));
  1069. goto done;
  1070. }
  1071. if (len < sizeof(*rp)) {
  1072. error("Too small info reply (%u bytes)", len);
  1073. goto done;
  1074. }
  1075. print("hci%u:\tPrimary controller", index);
  1076. ba2str(&rp->bdaddr, addr);
  1077. print("\taddr %s version %u manufacturer %u",
  1078. addr, rp->version, le16_to_cpu(rp->manufacturer));
  1079. supported_settings = le32_to_cpu(rp->supported_settings);
  1080. print("\tsupported settings: %s", settings2str(supported_settings));
  1081. current_settings = le32_to_cpu(rp->current_settings);
  1082. print("\tcurrent settings: %s", settings2str(current_settings));
  1083. if (supported_settings & MGMT_SETTING_CONFIGURATION) {
  1084. if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
  1085. index, 0, NULL, config_options_rsp,
  1086. UINT_TO_PTR(index), NULL)) {
  1087. error("Unable to send read_config cmd");
  1088. goto done;
  1089. }
  1090. return;
  1091. }
  1092. done:
  1093. pending_index--;
  1094. if (pending_index > 0)
  1095. return;
  1096. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1097. }
  1098. static void index_rsp(uint8_t status, uint16_t len, const void *param,
  1099. void *user_data)
  1100. {
  1101. const struct mgmt_rp_read_index_list *rp = param;
  1102. struct mgmt *mgmt = user_data;
  1103. uint16_t count;
  1104. unsigned int i;
  1105. if (status != 0) {
  1106. error("Reading index list failed with status 0x%02x (%s)",
  1107. status, mgmt_errstr(status));
  1108. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1109. }
  1110. if (len < sizeof(*rp)) {
  1111. error("Too small index list reply (%u bytes)", len);
  1112. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1113. }
  1114. count = le16_to_cpu(rp->num_controllers);
  1115. if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
  1116. error("Index count (%u) doesn't match reply length (%u)",
  1117. count, len);
  1118. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1119. }
  1120. print("Index list with %u item%s", count, count != 1 ? "s" : "");
  1121. for (i = 0; i < count; i++) {
  1122. uint16_t index = le16_to_cpu(rp->index[i]);
  1123. if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
  1124. info_rsp, UINT_TO_PTR(index), NULL)) {
  1125. error("Unable to send read_info cmd");
  1126. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1127. }
  1128. pending_index++;
  1129. }
  1130. if (!count)
  1131. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1132. }
  1133. static void cmd_info(int argc, char **argv)
  1134. {
  1135. if (mgmt_index == MGMT_INDEX_NONE) {
  1136. if (!mgmt_send(mgmt, MGMT_OP_READ_INDEX_LIST,
  1137. MGMT_INDEX_NONE, 0, NULL,
  1138. index_rsp, mgmt, NULL)) {
  1139. error("Unable to send index_list cmd");
  1140. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1141. }
  1142. return;
  1143. }
  1144. if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, mgmt_index, 0, NULL, info_rsp,
  1145. UINT_TO_PTR(mgmt_index), NULL)) {
  1146. error("Unable to send read_info cmd");
  1147. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1148. }
  1149. }
  1150. static void ext_index_rsp(uint8_t status, uint16_t len, const void *param,
  1151. void *user_data)
  1152. {
  1153. const struct mgmt_rp_read_ext_index_list *rp = param;
  1154. uint16_t count;
  1155. unsigned int i;
  1156. if (status != 0) {
  1157. error("Reading ext index list failed with status 0x%02x (%s)",
  1158. status, mgmt_errstr(status));
  1159. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1160. }
  1161. if (len < sizeof(*rp)) {
  1162. error("Too small ext index list reply (%u bytes)", len);
  1163. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1164. }
  1165. count = get_le16(&rp->num_controllers);
  1166. if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
  1167. error("Index count (%u) doesn't match reply length (%u)",
  1168. count, len);
  1169. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1170. }
  1171. print("Extended index list with %u item%s",
  1172. count, count != 1 ? "s" : "");
  1173. for (i = 0; i < count; i++) {
  1174. uint16_t index = le16_to_cpu(rp->entry[i].index);
  1175. char *busstr = hci_bustostr(rp->entry[i].bus);
  1176. switch (rp->entry[i].type) {
  1177. case 0x00:
  1178. print("Primary controller (hci%u,%s)", index, busstr);
  1179. if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INFO,
  1180. index, 0, NULL, ext_info_rsp,
  1181. UINT_TO_PTR(index), NULL)) {
  1182. error("Unable to send read_ext_info cmd");
  1183. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1184. }
  1185. pending_index++;
  1186. break;
  1187. case 0x01:
  1188. print("Unconfigured controller (hci%u,%s)",
  1189. index, busstr);
  1190. if (!mgmt_send(mgmt, MGMT_OP_READ_CONFIG_INFO,
  1191. index, 0, NULL, config_info_rsp,
  1192. UINT_TO_PTR(index), NULL)) {
  1193. error("Unable to send read_config cmd");
  1194. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1195. }
  1196. pending_index++;
  1197. break;
  1198. case 0x02:
  1199. print("AMP controller (hci%u,%s)", index, busstr);
  1200. break;
  1201. default:
  1202. print("Type %u controller (hci%u,%s)",
  1203. rp->entry[i].type, index, busstr);
  1204. break;
  1205. }
  1206. }
  1207. print("");
  1208. if (!count)
  1209. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1210. }
  1211. static void cmd_extinfo(int argc, char **argv)
  1212. {
  1213. if (mgmt_index == MGMT_INDEX_NONE) {
  1214. if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
  1215. MGMT_INDEX_NONE, 0, NULL,
  1216. ext_index_rsp, mgmt, NULL)) {
  1217. error("Unable to send ext_index_list cmd");
  1218. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1219. }
  1220. return;
  1221. }
  1222. if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INFO, mgmt_index, 0, NULL,
  1223. ext_info_rsp,
  1224. UINT_TO_PTR(mgmt_index), NULL)) {
  1225. error("Unable to send ext_read_info cmd");
  1226. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1227. }
  1228. }
  1229. static void print_cap(const uint8_t *cap, uint16_t cap_len)
  1230. {
  1231. uint16_t parsed = 0;
  1232. while (parsed < cap_len - 1) {
  1233. uint8_t field_len = cap[0];
  1234. if (field_len == 0)
  1235. break;
  1236. parsed += field_len + 1;
  1237. if (parsed > cap_len)
  1238. break;
  1239. switch (cap[1]) {
  1240. case 0x01:
  1241. print("\tFlags: 0x%02x", cap[2]);
  1242. break;
  1243. case 0x02:
  1244. print("\tMax Key Size (BR/EDR): %u", cap[2]);
  1245. break;
  1246. case 0x03:
  1247. print("\tMax Key Size (LE): %u", cap[2]);
  1248. break;
  1249. default:
  1250. print("\tType %u: %u byte%s", cap[1], field_len - 1,
  1251. (field_len - 1) == 1 ? "" : "s");
  1252. break;
  1253. }
  1254. cap += field_len + 1;
  1255. }
  1256. }
  1257. static void sec_info_rsp(uint8_t status, uint16_t len, const void *param,
  1258. void *user_data)
  1259. {
  1260. const struct mgmt_rp_read_controller_cap *rp = param;
  1261. uint16_t index = PTR_TO_UINT(user_data);
  1262. if (status != 0) {
  1263. error("Reading hci%u security failed with status 0x%02x (%s)",
  1264. index, status, mgmt_errstr(status));
  1265. goto done;
  1266. }
  1267. if (len < sizeof(*rp)) {
  1268. error("Too small info reply (%u bytes)", len);
  1269. goto done;
  1270. }
  1271. print("Primary controller (hci%u)", index);
  1272. print("\tInfo length: %u", le16_to_cpu(rp->cap_len));
  1273. print_cap(rp->cap, le16_to_cpu(rp->cap_len));
  1274. done:
  1275. pending_index--;
  1276. if (pending_index > 0)
  1277. return;
  1278. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1279. }
  1280. static void sec_index_rsp(uint8_t status, uint16_t len, const void *param,
  1281. void *user_data)
  1282. {
  1283. const struct mgmt_rp_read_ext_index_list *rp = param;
  1284. uint16_t count;
  1285. unsigned int i;
  1286. if (status != 0) {
  1287. error("Reading ext index list failed with status 0x%02x (%s)",
  1288. status, mgmt_errstr(status));
  1289. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1290. }
  1291. if (len < sizeof(*rp)) {
  1292. error("Too small ext index list reply (%u bytes)", len);
  1293. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1294. }
  1295. count = get_le16(&rp->num_controllers);
  1296. if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
  1297. error("Index count (%u) doesn't match reply length (%u)",
  1298. count, len);
  1299. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1300. }
  1301. for (i = 0; i < count; i++) {
  1302. uint16_t index = le16_to_cpu(rp->entry[i].index);
  1303. if (rp->entry[i].type != 0x00)
  1304. continue;
  1305. if (!mgmt_send(mgmt, MGMT_OP_READ_CONTROLLER_CAP,
  1306. index, 0, NULL, sec_info_rsp,
  1307. UINT_TO_PTR(index), NULL)) {
  1308. error("Unable to send read_security_info cmd");
  1309. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1310. }
  1311. pending_index++;
  1312. }
  1313. if (!count)
  1314. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1315. }
  1316. static void cmd_secinfo(int argc, char **argv)
  1317. {
  1318. if (mgmt_index == MGMT_INDEX_NONE) {
  1319. if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
  1320. MGMT_INDEX_NONE, 0, NULL,
  1321. sec_index_rsp, mgmt, NULL)) {
  1322. error("Unable to send ext_index_list cmd");
  1323. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1324. }
  1325. return;
  1326. }
  1327. if (!mgmt_send(mgmt, MGMT_OP_READ_CONTROLLER_CAP, mgmt_index, 0, NULL,
  1328. sec_info_rsp,
  1329. UINT_TO_PTR(mgmt_index), NULL)) {
  1330. error("Unable to send read_security_info cmd");
  1331. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1332. }
  1333. }
  1334. static void exp_info_rsp(uint8_t status, uint16_t len, const void *param,
  1335. void *user_data)
  1336. {
  1337. const struct mgmt_rp_read_exp_features_info *rp = param;
  1338. uint16_t index = PTR_TO_UINT(user_data);
  1339. if (status != 0) {
  1340. error("Reading hci%u exp features failed with status 0x%02x (%s)",
  1341. index, status, mgmt_errstr(status));
  1342. goto done;
  1343. }
  1344. if (len < sizeof(*rp)) {
  1345. error("Too small info reply (%u bytes)", len);
  1346. goto done;
  1347. }
  1348. if (index == MGMT_INDEX_NONE)
  1349. print("Global");
  1350. else
  1351. print("Primary controller (hci%u)", index);
  1352. print("\tNumber of experimental features: %u",
  1353. le16_to_cpu(rp->feature_count));
  1354. done:
  1355. pending_index--;
  1356. if (pending_index > 0)
  1357. return;
  1358. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1359. }
  1360. static void exp_index_rsp(uint8_t status, uint16_t len, const void *param,
  1361. void *user_data)
  1362. {
  1363. const struct mgmt_rp_read_ext_index_list *rp = param;
  1364. uint16_t count;
  1365. unsigned int i;
  1366. if (status != 0) {
  1367. error("Reading ext index list failed with status 0x%02x (%s)",
  1368. status, mgmt_errstr(status));
  1369. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1370. }
  1371. if (len < sizeof(*rp)) {
  1372. error("Too small ext index list reply (%u bytes)", len);
  1373. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1374. }
  1375. count = get_le16(&rp->num_controllers);
  1376. if (len < sizeof(*rp) + count * (sizeof(uint16_t) + sizeof(uint8_t))) {
  1377. error("Index count (%u) doesn't match reply length (%u)",
  1378. count, len);
  1379. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1380. }
  1381. for (i = 0; i < count; i++) {
  1382. uint16_t index = le16_to_cpu(rp->entry[i].index);
  1383. if (rp->entry[i].type != 0x00)
  1384. continue;
  1385. if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
  1386. index, 0, NULL, exp_info_rsp,
  1387. UINT_TO_PTR(index), NULL)) {
  1388. error("Unable to send read_exp_features_info cmd");
  1389. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1390. }
  1391. pending_index++;
  1392. }
  1393. }
  1394. static void cmd_expinfo(int argc, char **argv)
  1395. {
  1396. if (mgmt_index == MGMT_INDEX_NONE) {
  1397. if (!mgmt_send(mgmt, MGMT_OP_READ_EXT_INDEX_LIST,
  1398. MGMT_INDEX_NONE, 0, NULL,
  1399. exp_index_rsp, mgmt, NULL)) {
  1400. error("Unable to send ext_index_list cmd");
  1401. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1402. }
  1403. if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO,
  1404. MGMT_INDEX_NONE, 0, NULL,
  1405. exp_info_rsp,
  1406. UINT_TO_PTR(MGMT_INDEX_NONE), NULL)) {
  1407. error("Unable to send read_exp_features_info cmd");
  1408. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1409. }
  1410. pending_index++;
  1411. return;
  1412. }
  1413. if (!mgmt_send(mgmt, MGMT_OP_READ_EXP_FEATURES_INFO, mgmt_index,
  1414. 0, NULL, exp_info_rsp,
  1415. UINT_TO_PTR(mgmt_index), NULL)) {
  1416. error("Unable to send read_exp_features_info cmd");
  1417. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1418. }
  1419. }
  1420. static void exp_debug_rsp(uint8_t status, uint16_t len, const void *param,
  1421. void *user_data)
  1422. {
  1423. if (status != 0)
  1424. error("Set debug feature failed with status 0x%02x (%s)",
  1425. status, mgmt_errstr(status));
  1426. else
  1427. print("Debug feature successfully set");
  1428. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1429. }
  1430. static void cmd_exp_debug(int argc, char **argv)
  1431. {
  1432. /* d4992530-b9ec-469f-ab01-6c481c47da1c */
  1433. static const uint8_t uuid[16] = {
  1434. 0x1c, 0xda, 0x47, 0x1c, 0x48, 0x6c, 0x01, 0xab,
  1435. 0x9f, 0x46, 0xec, 0xb9, 0x30, 0x25, 0x99, 0xd4,
  1436. };
  1437. struct mgmt_cp_set_exp_feature cp;
  1438. uint8_t val;
  1439. if (parse_setting(argc, argv, &val) == false)
  1440. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1441. memset(&cp, 0, sizeof(cp));
  1442. memcpy(cp.uuid, uuid, 16);
  1443. cp.action = val;
  1444. if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
  1445. sizeof(cp), &cp, exp_debug_rsp, NULL, NULL) == 0) {
  1446. error("Unable to send debug feature cmd");
  1447. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1448. }
  1449. }
  1450. static void exp_privacy_rsp(uint8_t status, uint16_t len, const void *param,
  1451. void *user_data)
  1452. {
  1453. if (status != 0)
  1454. error("Set LL privacy feature failed with status 0x%02x (%s)",
  1455. status, mgmt_errstr(status));
  1456. else
  1457. print("LL privacy feature successfully set");
  1458. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1459. }
  1460. static void cmd_exp_privacy(int argc, char **argv)
  1461. {
  1462. /* 15c0a148-c273-11ea-b3de-0242ac130004 */
  1463. static const uint8_t uuid[16] = {
  1464. 0x04, 0x00, 0x13, 0xac, 0x42, 0x02, 0xde, 0xb3,
  1465. 0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
  1466. };
  1467. struct mgmt_cp_set_exp_feature cp;
  1468. uint8_t val;
  1469. if (parse_setting(argc, argv, &val) == false)
  1470. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1471. memset(&cp, 0, sizeof(cp));
  1472. memcpy(cp.uuid, uuid, 16);
  1473. cp.action = val;
  1474. if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
  1475. sizeof(cp), &cp, exp_privacy_rsp, NULL, NULL) == 0) {
  1476. error("Unable to send LL privacy feature cmd");
  1477. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1478. }
  1479. }
  1480. static void exp_quality_rsp(uint8_t status, uint16_t len, const void *param,
  1481. void *user_data)
  1482. {
  1483. if (status != 0)
  1484. error("Set Quality Report feature failed: 0x%02x (%s)",
  1485. status, mgmt_errstr(status));
  1486. else
  1487. print("Quality Report feature successfully set");
  1488. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1489. }
  1490. static void cmd_exp_quality(int argc, char **argv)
  1491. {
  1492. /* 330859bc-7506-492d-9370-9a6f0614037f */
  1493. static const uint8_t uuid[16] = {
  1494. 0x7f, 0x03, 0x14, 0x06, 0x6f, 0x9a, 0x70, 0x93,
  1495. 0x2d, 0x49, 0x06, 0x75, 0xbc, 0x59, 0x08, 0x33,
  1496. };
  1497. struct mgmt_cp_set_exp_feature cp;
  1498. uint8_t val;
  1499. if (mgmt_index == MGMT_INDEX_NONE) {
  1500. error("BQR feature requires a valid controller index");
  1501. return;
  1502. }
  1503. if (parse_setting(argc, argv, &val) == false)
  1504. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1505. if (val != 0 && val != 1) {
  1506. error("Invalid value %u", val);
  1507. return;
  1508. }
  1509. memset(&cp, 0, sizeof(cp));
  1510. memcpy(cp.uuid, uuid, 16);
  1511. cp.action = val;
  1512. if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, mgmt_index,
  1513. sizeof(cp), &cp, exp_quality_rsp, NULL, NULL) == 0) {
  1514. error("Unable to send quality report feature cmd");
  1515. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1516. }
  1517. }
  1518. static void print_mgmt_tlv(void *data, void *user_data)
  1519. {
  1520. const struct mgmt_tlv *entry = data;
  1521. char buf[256];
  1522. bin2hex(entry->value, entry->length, buf, sizeof(buf));
  1523. print("Type: 0x%04x\tLength: %02hhu\tValue: %s", entry->type,
  1524. entry->length, buf);
  1525. }
  1526. static void read_sysconfig_rsp(uint8_t status, uint16_t len, const void *param,
  1527. void *user_data)
  1528. {
  1529. struct mgmt_tlv_list *tlv_list;
  1530. if (status != 0) {
  1531. error("Read system configuration failed with status "
  1532. "0x%02x (%s)", status, mgmt_errstr(status));
  1533. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1534. }
  1535. tlv_list = mgmt_tlv_list_load_from_buf(param, len);
  1536. if (!tlv_list) {
  1537. error("Unable to parse response of read system configuration");
  1538. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1539. }
  1540. mgmt_tlv_list_foreach(tlv_list, print_mgmt_tlv, NULL);
  1541. mgmt_tlv_list_free(tlv_list);
  1542. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1543. }
  1544. static void cmd_read_sysconfig(int argc, char **argv)
  1545. {
  1546. uint16_t index;
  1547. index = mgmt_index;
  1548. if (index == MGMT_INDEX_NONE)
  1549. index = 0;
  1550. if (!mgmt_send(mgmt, MGMT_OP_READ_DEF_SYSTEM_CONFIG, index,
  1551. 0, NULL, read_sysconfig_rsp, NULL, NULL)) {
  1552. error("Unable to send read system configuration cmd");
  1553. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1554. }
  1555. }
  1556. static bool parse_mgmt_tlv(const char *input, uint16_t *type, uint8_t *length,
  1557. uint8_t *value)
  1558. {
  1559. int i, value_starting_pos;
  1560. if (sscanf(input, "%4hx:%1hhu:%n", type, length,
  1561. &value_starting_pos) < 2) {
  1562. return false;
  1563. }
  1564. input += value_starting_pos;
  1565. if (*length * 2 != strlen(input))
  1566. return false;
  1567. for (i = 0; i < *length; i++) {
  1568. if (sscanf(input + i * 2, "%2hhx", &value[i]) < 1)
  1569. return false;
  1570. }
  1571. return true;
  1572. }
  1573. static void set_sysconfig_rsp(uint8_t status, uint16_t len, const void *param,
  1574. void *user_data)
  1575. {
  1576. if (status != MGMT_STATUS_SUCCESS) {
  1577. error("Could not set default system configuration with status "
  1578. "0x%02x (%s)", status, mgmt_errstr(status));
  1579. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1580. }
  1581. print("Set default system configuration success");
  1582. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1583. }
  1584. static bool set_sysconfig(int argc, char **argv)
  1585. {
  1586. struct mgmt_tlv_list *tlv_list = NULL;
  1587. int i;
  1588. uint16_t index, type;
  1589. uint8_t length;
  1590. uint8_t value[256] = {};
  1591. bool success = false;
  1592. index = mgmt_index;
  1593. if (index == MGMT_INDEX_NONE)
  1594. index = 0;
  1595. tlv_list = mgmt_tlv_list_new();
  1596. if (!tlv_list) {
  1597. error("tlv_list failed to init");
  1598. goto failed;
  1599. }
  1600. for (i = 0; i < argc; i++) {
  1601. if (!parse_mgmt_tlv(argv[i], &type, &length, value)) {
  1602. error("failed to parse");
  1603. goto failed;
  1604. }
  1605. if (!mgmt_tlv_add(tlv_list, type, length, value)) {
  1606. error("failed to add");
  1607. goto failed;
  1608. }
  1609. }
  1610. if (!mgmt_send_tlv(mgmt, MGMT_OP_SET_DEF_SYSTEM_CONFIG, index,
  1611. tlv_list, set_sysconfig_rsp, NULL, NULL)) {
  1612. error("Failed to send \"Set Default System Configuration\""
  1613. " command");
  1614. goto failed;
  1615. }
  1616. success = true;
  1617. failed:
  1618. if (tlv_list)
  1619. mgmt_tlv_list_free(tlv_list);
  1620. return success;
  1621. }
  1622. static void set_sysconfig_usage(void)
  1623. {
  1624. bt_shell_usage();
  1625. print("Parameters:\n\t-v <type:length:value>...\n"
  1626. "e.g.:\n\tset-sysconfig -v 001a:2:1234 001f:1:00");
  1627. }
  1628. static void cmd_set_sysconfig(int argc, char **argv)
  1629. {
  1630. bool success = false;
  1631. if (strcasecmp(argv[1], "-v") == 0 && argc > 2) {
  1632. argc -= 2;
  1633. argv += 2;
  1634. success = set_sysconfig(argc, argv);
  1635. }
  1636. if (!success) {
  1637. set_sysconfig_usage();
  1638. bt_shell_noninteractive_quit(EXIT_FAILURE);
  1639. }
  1640. }
  1641. static void auto_power_enable_rsp(uint8_t status, uint16_t len,
  1642. const void *param, void *user_data)
  1643. {
  1644. uint16_t index = PTR_TO_UINT(user_data);
  1645. print("Successfully enabled controller with index %u", index);
  1646. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1647. }
  1648. static void auto_power_info_rsp(uint8_t status, uint16_t len,
  1649. const void *param, void *user_data)
  1650. {
  1651. const struct mgmt_rp_read_info *rp = param;
  1652. uint16_t index = PTR_TO_UINT(user_data);
  1653. uint32_t supported_settings, current_settings, missing_settings;
  1654. uint8_t val = 0x01;
  1655. if (status) {
  1656. error("Reading info failed with status 0x%02x (%s)",
  1657. status, mgmt_errstr(status));
  1658. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1659. }
  1660. supported_settings = le32_to_cpu(rp->supported_settings);
  1661. current_settings = le32_to_cpu(rp->current_settings);
  1662. missing_settings = current_settings ^ supported_settings;
  1663. if (missing_settings & MGMT_SETTING_BREDR)
  1664. mgmt_send(mgmt, MGMT_OP_SET_BREDR, index, sizeof(val), &val,
  1665. NULL, NULL, NULL);
  1666. if (missing_settings & MGMT_SETTING_SSP)
  1667. mgmt_send(mgmt, MGMT_OP_SET_SSP, index, sizeof(val), &val,
  1668. NULL, NULL, NULL);
  1669. if (missing_settings & MGMT_SETTING_LE)
  1670. mgmt_send(mgmt, MGMT_OP_SET_LE, index, sizeof(val), &val,
  1671. NULL, NULL, NULL);
  1672. if (missing_settings & MGMT_SETTING_SECURE_CONN)
  1673. mgmt_send(mgmt, MGMT_OP_SET_SECURE_CONN, index,
  1674. sizeof(val), &val,
  1675. NULL, NULL, NULL);
  1676. if (missing_settings & MGMT_SETTING_BONDABLE)
  1677. mgmt_send(mgmt, MGMT_OP_SET_BONDABLE, index, sizeof(val), &val,
  1678. NULL, NULL, NULL);
  1679. if (current_settings & MGMT_SETTING_POWERED)
  1680. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1681. if (!mgmt_send(mgmt, MGMT_OP_SET_POWERED, index, sizeof(val), &val,
  1682. auto_power_enable_rsp,
  1683. UINT_TO_PTR(index), NULL)) {
  1684. error("Unable to send set powerd cmd");
  1685. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1686. }
  1687. }
  1688. static void auto_power_index_evt(uint16_t index, uint16_t len,
  1689. const void *param, void *user_data)
  1690. {
  1691. uint16_t index_filter = PTR_TO_UINT(user_data);
  1692. if (index != index_filter)
  1693. return;
  1694. print("New controller with index %u", index);
  1695. if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
  1696. auto_power_info_rsp,
  1697. UINT_TO_PTR(index), NULL)) {
  1698. error("Unable to send read info cmd");
  1699. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1700. }
  1701. }
  1702. static void auto_power_index_rsp(uint8_t status, uint16_t len,
  1703. const void *param, void *user_data)
  1704. {
  1705. const struct mgmt_rp_read_index_list *rp = param;
  1706. uint16_t index = PTR_TO_UINT(user_data);
  1707. uint16_t i, count;
  1708. bool found = false;
  1709. if (status) {
  1710. error("Reading index list failed with status 0x%02x (%s)",
  1711. status, mgmt_errstr(status));
  1712. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1713. }
  1714. count = le16_to_cpu(rp->num_controllers);
  1715. for (i = 0; i < count; i++) {
  1716. if (le16_to_cpu(rp->index[i]) == index)
  1717. found = true;
  1718. }
  1719. if (!found) {
  1720. print("Waiting for index %u to appear", index);
  1721. mgmt_register(mgmt, MGMT_EV_INDEX_ADDED, index,
  1722. auto_power_index_evt,
  1723. UINT_TO_PTR(index), NULL);
  1724. return;
  1725. }
  1726. print("Found controller with index %u", index);
  1727. if (!mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
  1728. auto_power_info_rsp,
  1729. UINT_TO_PTR(index), NULL)) {
  1730. error("Unable to send read info cmd");
  1731. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1732. }
  1733. }
  1734. static void cmd_auto_power(int argc, char **argv)
  1735. {
  1736. int index;
  1737. index = mgmt_index;
  1738. if (index == MGMT_INDEX_NONE)
  1739. index = 0;
  1740. if (!mgmt_send(mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL,
  1741. auto_power_index_rsp,
  1742. UINT_TO_PTR(index), NULL)) {
  1743. error("Unable to send read index list cmd");
  1744. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1745. }
  1746. }
  1747. static void get_flags_rsp(uint8_t status, uint16_t len, const void *param,
  1748. void *user_data)
  1749. {
  1750. const struct mgmt_rp_get_device_flags *rp = param;
  1751. if (status != 0) {
  1752. error("Get device flags failed with status 0x%02x (%s)",
  1753. status, mgmt_errstr(status));
  1754. bt_shell_noninteractive_quit(EXIT_FAILURE);
  1755. }
  1756. print("Supported Flags: 0x%08x", rp->supported_flags);
  1757. print("Current Flags: 0x%08x", rp->current_flags);
  1758. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1759. }
  1760. static struct option get_flags_options[] = {
  1761. { "help", 0, 0, 'h' },
  1762. { "type", 1, 0, 't' },
  1763. { 0, 0, 0, 0 }
  1764. };
  1765. static void cmd_get_flags(int argc, char **argv)
  1766. {
  1767. struct mgmt_cp_get_device_flags cp;
  1768. uint8_t type = BDADDR_BREDR;
  1769. char addr[18];
  1770. int opt;
  1771. uint16_t index;
  1772. while ((opt = getopt_long(argc, argv, "+t:h", get_flags_options,
  1773. NULL)) != -1) {
  1774. switch (opt) {
  1775. case 't':
  1776. type = strtol(optarg, NULL, 0);
  1777. break;
  1778. case 'h':
  1779. bt_shell_usage();
  1780. optind = 0;
  1781. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1782. default:
  1783. bt_shell_usage();
  1784. optind = 0;
  1785. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1786. }
  1787. }
  1788. argc -= optind;
  1789. argv += optind;
  1790. optind = 0;
  1791. if (argc < 1) {
  1792. bt_shell_usage();
  1793. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1794. }
  1795. index = mgmt_index;
  1796. if (index == MGMT_INDEX_NONE)
  1797. index = 0;
  1798. memset(&cp, 0, sizeof(cp));
  1799. str2ba(argv[0], &cp.addr.bdaddr);
  1800. cp.addr.type = type;
  1801. ba2str(&cp.addr.bdaddr, addr);
  1802. print("Get device flag of %s (%s)", addr, typestr(cp.addr.type));
  1803. if (mgmt_send(mgmt, MGMT_OP_GET_DEVICE_FLAGS, index, sizeof(cp), &cp,
  1804. get_flags_rsp, NULL, NULL) == 0) {
  1805. error("Unable to send Get Device Flags command");
  1806. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1807. }
  1808. }
  1809. static void set_flags_rsp(uint8_t status, uint16_t len, const void *param,
  1810. void *user_data)
  1811. {
  1812. if (status != 0) {
  1813. error("Set device flags failed with status 0x%02x (%s)",
  1814. status, mgmt_errstr(status));
  1815. bt_shell_noninteractive_quit(EXIT_FAILURE);
  1816. }
  1817. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1818. }
  1819. static struct option set_flags_options[] = {
  1820. { "help", 0, 0, 'h' },
  1821. { "type", 1, 0, 't' },
  1822. { "flags", 1, 0, 'f' },
  1823. { 0, 0, 0, 0 }
  1824. };
  1825. static void cmd_set_flags(int argc, char **argv)
  1826. {
  1827. struct mgmt_cp_set_device_flags cp;
  1828. uint8_t type = BDADDR_BREDR;
  1829. uint32_t flags = 0;
  1830. char addr[18];
  1831. int opt;
  1832. uint16_t index;
  1833. while ((opt = getopt_long(argc, argv, "+f:t:h", set_flags_options,
  1834. NULL)) != -1) {
  1835. switch (opt) {
  1836. case 'f':
  1837. flags = strtol(optarg, NULL, 0);
  1838. break;
  1839. case 't':
  1840. type = strtol(optarg, NULL, 0);
  1841. break;
  1842. case 'h':
  1843. bt_shell_usage();
  1844. optind = 0;
  1845. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1846. default:
  1847. bt_shell_usage();
  1848. optind = 0;
  1849. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1850. }
  1851. }
  1852. argc -= optind;
  1853. argv += optind;
  1854. optind = 0;
  1855. if (argc < 1) {
  1856. bt_shell_usage();
  1857. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1858. }
  1859. index = mgmt_index;
  1860. if (index == MGMT_INDEX_NONE)
  1861. index = 0;
  1862. memset(&cp, 0, sizeof(cp));
  1863. str2ba(argv[0], &cp.addr.bdaddr);
  1864. cp.addr.type = type;
  1865. cp.current_flags = flags;
  1866. ba2str(&cp.addr.bdaddr, addr);
  1867. print("Set device flag of %s (%s)", addr, typestr(cp.addr.type));
  1868. if (mgmt_send(mgmt, MGMT_OP_SET_DEVICE_FLAGS, index, sizeof(cp), &cp,
  1869. set_flags_rsp, NULL, NULL) == 0) {
  1870. error("Unable to send Set Device Flags command");
  1871. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1872. }
  1873. }
  1874. /* Wrapper to get the index and opcode to the response callback */
  1875. struct command_data {
  1876. uint16_t id;
  1877. uint16_t op;
  1878. void (*callback) (uint16_t id, uint16_t op, uint8_t status,
  1879. uint16_t len, const void *param);
  1880. };
  1881. static void cmd_rsp(uint8_t status, uint16_t len, const void *param,
  1882. void *user_data)
  1883. {
  1884. struct command_data *data = user_data;
  1885. data->callback(data->op, data->id, status, len, param);
  1886. }
  1887. static unsigned int send_cmd(struct mgmt *mgmt, uint16_t op, uint16_t id,
  1888. uint16_t len, const void *param,
  1889. void (*cb)(uint16_t id, uint16_t op,
  1890. uint8_t status, uint16_t len,
  1891. const void *param))
  1892. {
  1893. struct command_data *data;
  1894. unsigned int send_id;
  1895. data = new0(struct command_data, 1);
  1896. if (!data)
  1897. return 0;
  1898. data->id = id;
  1899. data->op = op;
  1900. data->callback = cb;
  1901. send_id = mgmt_send(mgmt, op, id, len, param, cmd_rsp, data, free);
  1902. if (send_id == 0)
  1903. free(data);
  1904. return send_id;
  1905. }
  1906. static void setting_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
  1907. const void *param)
  1908. {
  1909. const uint32_t *rp = param;
  1910. if (status != 0) {
  1911. error("%s for hci%u failed with status 0x%02x (%s)",
  1912. mgmt_opstr(op), id, status, mgmt_errstr(status));
  1913. goto done;
  1914. }
  1915. if (len < sizeof(*rp)) {
  1916. error("Too small %s response (%u bytes)",
  1917. mgmt_opstr(op), len);
  1918. goto done;
  1919. }
  1920. print("hci%u %s complete, settings: %s", id, mgmt_opstr(op),
  1921. settings2str(get_le32(rp)));
  1922. done:
  1923. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1924. }
  1925. static void cmd_setting(uint16_t op, int argc, char **argv)
  1926. {
  1927. int index;
  1928. uint8_t val;
  1929. if (parse_setting(argc, argv, &val) == false)
  1930. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1931. index = mgmt_index;
  1932. if (index == MGMT_INDEX_NONE)
  1933. index = 0;
  1934. if (send_cmd(mgmt, op, index, sizeof(val), &val, setting_rsp) == 0) {
  1935. error("Unable to send %s cmd", mgmt_opstr(op));
  1936. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1937. }
  1938. }
  1939. static void cmd_power(int argc, char **argv)
  1940. {
  1941. cmd_setting(MGMT_OP_SET_POWERED, argc, argv);
  1942. }
  1943. static void cmd_discov(int argc, char **argv)
  1944. {
  1945. struct mgmt_cp_set_discoverable cp;
  1946. uint16_t index;
  1947. memset(&cp, 0, sizeof(cp));
  1948. if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
  1949. cp.val = 1;
  1950. else if (strcasecmp(argv[1], "off") == 0)
  1951. cp.val = 0;
  1952. else if (strcasecmp(argv[1], "limited") == 0)
  1953. cp.val = 2;
  1954. else
  1955. cp.val = atoi(argv[1]);
  1956. if (argc > 2)
  1957. cp.timeout = htobs(atoi(argv[2]));
  1958. index = mgmt_index;
  1959. if (index == MGMT_INDEX_NONE)
  1960. index = 0;
  1961. if (send_cmd(mgmt, MGMT_OP_SET_DISCOVERABLE, index, sizeof(cp), &cp,
  1962. setting_rsp) == 0) {
  1963. error("Unable to send set_discoverable cmd");
  1964. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1965. }
  1966. }
  1967. static void cmd_connectable(int argc, char **argv)
  1968. {
  1969. cmd_setting(MGMT_OP_SET_CONNECTABLE, argc, argv);
  1970. }
  1971. static void cmd_fast_conn(int argc, char **argv)
  1972. {
  1973. cmd_setting(MGMT_OP_SET_FAST_CONNECTABLE, argc, argv);
  1974. }
  1975. static void cmd_bondable(int argc, char **argv)
  1976. {
  1977. cmd_setting(MGMT_OP_SET_BONDABLE, argc, argv);
  1978. }
  1979. static void cmd_linksec(int argc, char **argv)
  1980. {
  1981. cmd_setting(MGMT_OP_SET_LINK_SECURITY, argc, argv);
  1982. }
  1983. static void cmd_ssp(int argc, char **argv)
  1984. {
  1985. cmd_setting(MGMT_OP_SET_SSP, argc, argv);
  1986. }
  1987. static void cmd_sc(int argc, char **argv)
  1988. {
  1989. uint8_t val;
  1990. uint16_t index;
  1991. if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
  1992. val = 1;
  1993. else if (strcasecmp(argv[1], "off") == 0)
  1994. val = 0;
  1995. else if (strcasecmp(argv[1], "only") == 0)
  1996. val = 2;
  1997. else
  1998. val = atoi(argv[1]);
  1999. index = mgmt_index;
  2000. if (index == MGMT_INDEX_NONE)
  2001. index = 0;
  2002. if (send_cmd(mgmt, MGMT_OP_SET_SECURE_CONN, index,
  2003. sizeof(val), &val, setting_rsp) == 0) {
  2004. error("Unable to send set_secure_conn cmd");
  2005. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2006. }
  2007. }
  2008. static void cmd_hs(int argc, char **argv)
  2009. {
  2010. cmd_setting(MGMT_OP_SET_HS, argc, argv);
  2011. }
  2012. static void cmd_le(int argc, char **argv)
  2013. {
  2014. cmd_setting(MGMT_OP_SET_LE, argc, argv);
  2015. }
  2016. static void cmd_advertising(int argc, char **argv)
  2017. {
  2018. cmd_setting(MGMT_OP_SET_ADVERTISING, argc, argv);
  2019. }
  2020. static void cmd_bredr(int argc, char **argv)
  2021. {
  2022. cmd_setting(MGMT_OP_SET_BREDR, argc, argv);
  2023. }
  2024. static void cmd_privacy(int argc, char **argv)
  2025. {
  2026. struct mgmt_cp_set_privacy cp;
  2027. uint16_t index;
  2028. if (parse_setting(argc, argv, &cp.privacy) == false)
  2029. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2030. index = mgmt_index;
  2031. if (index == MGMT_INDEX_NONE)
  2032. index = 0;
  2033. if (argc > 2) {
  2034. if (hex2bin(argv[2], cp.irk,
  2035. sizeof(cp.irk)) != sizeof(cp.irk)) {
  2036. error("Invalid key format");
  2037. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2038. }
  2039. } else {
  2040. int fd;
  2041. fd = open("/dev/urandom", O_RDONLY);
  2042. if (fd < 0) {
  2043. error("open(/dev/urandom): %s", strerror(errno));
  2044. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2045. }
  2046. if (read(fd, cp.irk, sizeof(cp.irk)) != sizeof(cp.irk)) {
  2047. error("Reading from urandom failed");
  2048. close(fd);
  2049. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2050. }
  2051. close(fd);
  2052. }
  2053. if (send_cmd(mgmt, MGMT_OP_SET_PRIVACY, index, sizeof(cp), &cp,
  2054. setting_rsp) == 0) {
  2055. error("Unable to send Set Privacy command");
  2056. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2057. }
  2058. }
  2059. static void exp_offload_rsp(uint8_t status, uint16_t len, const void *param,
  2060. void *user_data)
  2061. {
  2062. if (status != 0)
  2063. error("Set offload codec failed with status 0x%02x (%s)",
  2064. status, mgmt_errstr(status));
  2065. else
  2066. print("Offload codec feature successfully set");
  2067. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2068. }
  2069. static void cmd_exp_offload_codecs(int argc, char **argv)
  2070. {
  2071. /* a6695ace-ee7f-4fb9-881a-5fac66c629af */
  2072. static const uint8_t uuid[16] = {
  2073. 0xaf, 0x29, 0xc6, 0x66, 0xac, 0x5f, 0x1a, 0x88,
  2074. 0xb9, 0x4f, 0x7f, 0xee, 0xce, 0x5a, 0x69, 0xa6,
  2075. };
  2076. struct mgmt_cp_set_exp_feature cp;
  2077. uint8_t val;
  2078. uint16_t index;
  2079. if (parse_setting(argc, argv, &val) == false)
  2080. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2081. index = mgmt_index;
  2082. if (index == MGMT_INDEX_NONE)
  2083. index = 0;
  2084. memset(&cp, 0, sizeof(cp));
  2085. memcpy(cp.uuid, uuid, 16);
  2086. cp.action = val;
  2087. if (mgmt_send(mgmt, MGMT_OP_SET_EXP_FEATURE, index,
  2088. sizeof(cp), &cp, exp_offload_rsp, NULL, NULL) == 0) {
  2089. error("Unable to send offload codecs feature cmd");
  2090. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2091. }
  2092. }
  2093. static void class_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
  2094. const void *param)
  2095. {
  2096. const struct mgmt_ev_class_of_dev_changed *rp = param;
  2097. if (len == 0 && status != 0) {
  2098. error("%s failed, status 0x%02x (%s)",
  2099. mgmt_opstr(op), status, mgmt_errstr(status));
  2100. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2101. }
  2102. if (len != sizeof(*rp)) {
  2103. error("Unexpected %s len %u", mgmt_opstr(op), len);
  2104. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2105. }
  2106. print("%s succeeded. Class 0x%02x%02x%02x", mgmt_opstr(op),
  2107. rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
  2108. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2109. }
  2110. static void cmd_class(int argc, char **argv)
  2111. {
  2112. uint8_t class[2];
  2113. uint16_t index;
  2114. class[0] = atoi(argv[1]);
  2115. class[1] = atoi(argv[2]);
  2116. index = mgmt_index;
  2117. if (index == MGMT_INDEX_NONE)
  2118. index = 0;
  2119. if (send_cmd(mgmt, MGMT_OP_SET_DEV_CLASS, index, sizeof(class), class,
  2120. class_rsp) == 0) {
  2121. error("Unable to send set_dev_class cmd");
  2122. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2123. }
  2124. }
  2125. static void disconnect_rsp(uint8_t status, uint16_t len, const void *param,
  2126. void *user_data)
  2127. {
  2128. const struct mgmt_rp_disconnect *rp = param;
  2129. char addr[18];
  2130. if (len == 0 && status != 0) {
  2131. error("Disconnect failed with status 0x%02x (%s)",
  2132. status, mgmt_errstr(status));
  2133. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2134. }
  2135. if (len != sizeof(*rp)) {
  2136. error("Invalid disconnect response length (%u)", len);
  2137. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2138. }
  2139. ba2str(&rp->addr.bdaddr, addr);
  2140. if (status == 0)
  2141. print("%s disconnected", addr);
  2142. else
  2143. error("Disconnecting %s failed with status 0x%02x (%s)",
  2144. addr, status, mgmt_errstr(status));
  2145. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2146. }
  2147. static struct option disconnect_options[] = {
  2148. { "help", 0, 0, 'h' },
  2149. { "type", 1, 0, 't' },
  2150. { 0, 0, 0, 0 }
  2151. };
  2152. static void cmd_disconnect(int argc, char **argv)
  2153. {
  2154. struct mgmt_cp_disconnect cp;
  2155. uint8_t type = BDADDR_BREDR;
  2156. int opt;
  2157. uint16_t index;
  2158. while ((opt = getopt_long(argc, argv, "+t:h", disconnect_options,
  2159. NULL)) != -1) {
  2160. switch (opt) {
  2161. case 't':
  2162. type = strtol(optarg, NULL, 0);
  2163. break;
  2164. case 'h':
  2165. bt_shell_usage();
  2166. optind = 0;
  2167. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2168. default:
  2169. bt_shell_usage();
  2170. optind = 0;
  2171. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2172. }
  2173. }
  2174. argc -= optind;
  2175. argv += optind;
  2176. optind = 0;
  2177. index = mgmt_index;
  2178. if (index == MGMT_INDEX_NONE)
  2179. index = 0;
  2180. memset(&cp, 0, sizeof(cp));
  2181. str2ba(argv[0], &cp.addr.bdaddr);
  2182. cp.addr.type = type;
  2183. if (mgmt_send(mgmt, MGMT_OP_DISCONNECT, index, sizeof(cp), &cp,
  2184. disconnect_rsp, NULL, NULL) == 0) {
  2185. error("Unable to send disconnect cmd");
  2186. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2187. }
  2188. }
  2189. static void con_rsp(uint8_t status, uint16_t len, const void *param,
  2190. void *user_data)
  2191. {
  2192. const struct mgmt_rp_get_connections *rp = param;
  2193. uint16_t count, i;
  2194. if (len < sizeof(*rp)) {
  2195. error("Too small (%u bytes) get_connections rsp", len);
  2196. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2197. }
  2198. count = get_le16(&rp->conn_count);
  2199. if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
  2200. error("Invalid get_connections length (count=%u, len=%u)",
  2201. count, len);
  2202. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2203. }
  2204. for (i = 0; i < count; i++) {
  2205. char addr[18];
  2206. ba2str(&rp->addr[i].bdaddr, addr);
  2207. print("%s type %s", addr, typestr(rp->addr[i].type));
  2208. }
  2209. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2210. }
  2211. static void cmd_con(int argc, char **argv)
  2212. {
  2213. uint16_t index;
  2214. index = mgmt_index;
  2215. if (index == MGMT_INDEX_NONE)
  2216. index = 0;
  2217. if (mgmt_send(mgmt, MGMT_OP_GET_CONNECTIONS, index, 0, NULL,
  2218. con_rsp, NULL, NULL) == 0) {
  2219. error("Unable to send get_connections cmd");
  2220. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2221. }
  2222. }
  2223. static void find_service_rsp(uint8_t status, uint16_t len, const void *param,
  2224. void *user_data)
  2225. {
  2226. if (status != 0) {
  2227. error("Start Service Discovery failed: status 0x%02x (%s)",
  2228. status, mgmt_errstr(status));
  2229. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2230. }
  2231. print("Service discovery started");
  2232. discovery = true;
  2233. }
  2234. static struct option find_service_options[] = {
  2235. { "help", no_argument, 0, 'h' },
  2236. { "le-only", no_argument, 0, 'l' },
  2237. { "bredr-only", no_argument, 0, 'b' },
  2238. { "uuid", required_argument, 0, 'u' },
  2239. { "rssi", required_argument, 0, 'r' },
  2240. { 0, 0, 0, 0 }
  2241. };
  2242. static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
  2243. {
  2244. if (uuid->type == SDP_UUID16)
  2245. sdp_uuid16_to_uuid128(uuid128, uuid);
  2246. else if (uuid->type == SDP_UUID32)
  2247. sdp_uuid32_to_uuid128(uuid128, uuid);
  2248. else
  2249. memcpy(uuid128, uuid, sizeof(*uuid));
  2250. }
  2251. #define MAX_UUIDS 4
  2252. static void cmd_find_service(int argc, char **argv)
  2253. {
  2254. struct mgmt_cp_start_service_discovery *cp;
  2255. uint8_t buf[sizeof(*cp) + 16 * MAX_UUIDS];
  2256. uuid_t uuid;
  2257. uint128_t uint128;
  2258. uuid_t uuid128;
  2259. uint8_t type = SCAN_TYPE_DUAL;
  2260. int8_t rssi;
  2261. uint16_t count;
  2262. int opt;
  2263. uint16_t index;
  2264. index = mgmt_index;
  2265. if (index == MGMT_INDEX_NONE)
  2266. index = 0;
  2267. rssi = 127;
  2268. count = 0;
  2269. while ((opt = getopt_long(argc, argv, "+lbu:r:h",
  2270. find_service_options, NULL)) != -1) {
  2271. switch (opt) {
  2272. case 'l':
  2273. type &= ~SCAN_TYPE_BREDR;
  2274. type |= SCAN_TYPE_LE;
  2275. break;
  2276. case 'b':
  2277. type |= SCAN_TYPE_BREDR;
  2278. type &= ~SCAN_TYPE_LE;
  2279. break;
  2280. case 'u':
  2281. if (count == MAX_UUIDS) {
  2282. print("Max %u UUIDs supported", MAX_UUIDS);
  2283. optind = 0;
  2284. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2285. }
  2286. if (bt_string2uuid(&uuid, optarg) < 0) {
  2287. print("Invalid UUID: %s", optarg);
  2288. optind = 0;
  2289. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2290. }
  2291. cp = (void *) buf;
  2292. uuid_to_uuid128(&uuid128, &uuid);
  2293. ntoh128((uint128_t *) uuid128.value.uuid128.data,
  2294. &uint128);
  2295. htob128(&uint128, (uint128_t *) cp->uuids[count++]);
  2296. break;
  2297. case 'r':
  2298. rssi = atoi(optarg);
  2299. break;
  2300. case 'h':
  2301. bt_shell_usage();
  2302. optind = 0;
  2303. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2304. default:
  2305. bt_shell_usage();
  2306. optind = 0;
  2307. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2308. }
  2309. }
  2310. argc -= optind;
  2311. argv += optind;
  2312. optind = 0;
  2313. cp = (void *) buf;
  2314. cp->type = type;
  2315. cp->rssi = rssi;
  2316. cp->uuid_count = cpu_to_le16(count);
  2317. if (mgmt_send(mgmt, MGMT_OP_START_SERVICE_DISCOVERY, index,
  2318. sizeof(*cp) + count * 16, cp,
  2319. find_service_rsp, NULL, NULL) == 0) {
  2320. error("Unable to send start_service_discovery cmd");
  2321. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2322. }
  2323. }
  2324. static void find_rsp(uint8_t status, uint16_t len, const void *param,
  2325. void *user_data)
  2326. {
  2327. if (status != 0) {
  2328. error("Unable to start discovery. status 0x%02x (%s)",
  2329. status, mgmt_errstr(status));
  2330. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2331. }
  2332. print("Discovery started");
  2333. discovery = true;
  2334. }
  2335. static struct option find_options[] = {
  2336. { "help", 0, 0, 'h' },
  2337. { "le-only", 1, 0, 'l' },
  2338. { "bredr-only", 1, 0, 'b' },
  2339. { "limited", 1, 0, 'L' },
  2340. { 0, 0, 0, 0 }
  2341. };
  2342. static void cmd_find(int argc, char **argv)
  2343. {
  2344. struct mgmt_cp_start_discovery cp;
  2345. uint8_t op = MGMT_OP_START_DISCOVERY;
  2346. uint8_t type = SCAN_TYPE_DUAL;
  2347. int opt;
  2348. uint16_t index;
  2349. index = mgmt_index;
  2350. if (index == MGMT_INDEX_NONE)
  2351. index = 0;
  2352. while ((opt = getopt_long(argc, argv, "+lbLh", find_options,
  2353. NULL)) != -1) {
  2354. switch (opt) {
  2355. case 'l':
  2356. type &= ~SCAN_TYPE_BREDR;
  2357. type |= SCAN_TYPE_LE;
  2358. break;
  2359. case 'b':
  2360. type |= SCAN_TYPE_BREDR;
  2361. type &= ~SCAN_TYPE_LE;
  2362. break;
  2363. case 'L':
  2364. op = MGMT_OP_START_LIMITED_DISCOVERY;
  2365. break;
  2366. case 'h':
  2367. bt_shell_usage();
  2368. optind = 0;
  2369. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2370. default:
  2371. bt_shell_usage();
  2372. optind = 0;
  2373. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2374. }
  2375. }
  2376. argc -= optind;
  2377. argv += optind;
  2378. optind = 0;
  2379. memset(&cp, 0, sizeof(cp));
  2380. cp.type = type;
  2381. if (mgmt_send(mgmt, op, index, sizeof(cp), &cp, find_rsp,
  2382. NULL, NULL) == 0) {
  2383. error("Unable to send start_discovery cmd");
  2384. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2385. }
  2386. }
  2387. static void stop_find_rsp(uint8_t status, uint16_t len, const void *param,
  2388. void *user_data)
  2389. {
  2390. if (status != 0) {
  2391. error("Stop Discovery failed: status 0x%02x (%s)",
  2392. status, mgmt_errstr(status));
  2393. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2394. }
  2395. print("Discovery stopped");
  2396. discovery = false;
  2397. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2398. }
  2399. static struct option stop_find_options[] = {
  2400. { "help", 0, 0, 'h' },
  2401. { "le-only", 1, 0, 'l' },
  2402. { "bredr-only", 1, 0, 'b' },
  2403. { 0, 0, 0, 0 }
  2404. };
  2405. static void cmd_stop_find(int argc, char **argv)
  2406. {
  2407. struct mgmt_cp_stop_discovery cp;
  2408. uint8_t type = SCAN_TYPE_DUAL;
  2409. int opt;
  2410. uint16_t index;
  2411. index = mgmt_index;
  2412. if (index == MGMT_INDEX_NONE)
  2413. index = 0;
  2414. while ((opt = getopt_long(argc, argv, "+lbh", stop_find_options,
  2415. NULL)) != -1) {
  2416. switch (opt) {
  2417. case 'l':
  2418. type &= ~SCAN_TYPE_BREDR;
  2419. type |= SCAN_TYPE_LE;
  2420. break;
  2421. case 'b':
  2422. type |= SCAN_TYPE_BREDR;
  2423. type &= ~SCAN_TYPE_LE;
  2424. break;
  2425. case 'h':
  2426. default:
  2427. bt_shell_usage();
  2428. optind = 0;
  2429. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2430. }
  2431. }
  2432. argc -= optind;
  2433. argv += optind;
  2434. optind = 0;
  2435. memset(&cp, 0, sizeof(cp));
  2436. cp.type = type;
  2437. if (mgmt_send(mgmt, MGMT_OP_STOP_DISCOVERY, index, sizeof(cp), &cp,
  2438. stop_find_rsp, NULL, NULL) == 0) {
  2439. error("Unable to send stop_discovery cmd");
  2440. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2441. }
  2442. }
  2443. static void name_rsp(uint8_t status, uint16_t len, const void *param,
  2444. void *user_data)
  2445. {
  2446. if (status != 0)
  2447. error("Unable to set local name with status 0x%02x (%s)",
  2448. status, mgmt_errstr(status));
  2449. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2450. }
  2451. static void cmd_name(int argc, char **argv)
  2452. {
  2453. struct mgmt_cp_set_local_name cp;
  2454. uint16_t index;
  2455. index = mgmt_index;
  2456. if (index == MGMT_INDEX_NONE)
  2457. index = 0;
  2458. memset(&cp, 0, sizeof(cp));
  2459. strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
  2460. if (argc > 2)
  2461. strncpy((char *) cp.short_name, argv[2],
  2462. MGMT_MAX_SHORT_NAME_LENGTH - 1);
  2463. if (mgmt_send(mgmt, MGMT_OP_SET_LOCAL_NAME, index, sizeof(cp), &cp,
  2464. name_rsp, NULL, NULL) == 0) {
  2465. error("Unable to send set_name cmd");
  2466. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2467. }
  2468. }
  2469. static void pair_rsp(uint8_t status, uint16_t len, const void *param,
  2470. void *user_data)
  2471. {
  2472. const struct mgmt_rp_pair_device *rp = param;
  2473. char addr[18];
  2474. if (len == 0 && status != 0) {
  2475. error("Pairing failed with status 0x%02x (%s)",
  2476. status, mgmt_errstr(status));
  2477. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2478. }
  2479. if (len != sizeof(*rp)) {
  2480. error("Unexpected pair_rsp len %u", len);
  2481. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2482. }
  2483. ba2str(&rp->addr.bdaddr, addr);
  2484. if (status)
  2485. error("Pairing with %s (%s) failed. status 0x%02x (%s)",
  2486. addr, typestr(rp->addr.type), status,
  2487. mgmt_errstr(status));
  2488. else
  2489. print("Paired with %s (%s)", addr, typestr(rp->addr.type));
  2490. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2491. }
  2492. static struct option pair_options[] = {
  2493. { "help", 0, 0, 'h' },
  2494. { "capability", 1, 0, 'c' },
  2495. { "type", 1, 0, 't' },
  2496. { 0, 0, 0, 0 }
  2497. };
  2498. static void cmd_pair(int argc, char **argv)
  2499. {
  2500. struct mgmt_cp_pair_device cp;
  2501. uint8_t cap = 0x01;
  2502. uint8_t type = BDADDR_BREDR;
  2503. char addr[18];
  2504. int opt;
  2505. uint16_t index;
  2506. while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
  2507. NULL)) != -1) {
  2508. switch (opt) {
  2509. case 'c':
  2510. cap = strtol(optarg, NULL, 0);
  2511. break;
  2512. case 't':
  2513. type = strtol(optarg, NULL, 0);
  2514. break;
  2515. case 'h':
  2516. bt_shell_usage();
  2517. optind = 0;
  2518. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2519. default:
  2520. bt_shell_usage();
  2521. optind = 0;
  2522. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2523. }
  2524. }
  2525. argc -= optind;
  2526. argv += optind;
  2527. optind = 0;
  2528. if (argc < 1) {
  2529. bt_shell_usage();
  2530. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2531. }
  2532. index = mgmt_index;
  2533. if (index == MGMT_INDEX_NONE)
  2534. index = 0;
  2535. memset(&cp, 0, sizeof(cp));
  2536. str2ba(argv[0], &cp.addr.bdaddr);
  2537. cp.addr.type = type;
  2538. cp.io_cap = cap;
  2539. ba2str(&cp.addr.bdaddr, addr);
  2540. print("Pairing with %s (%s)", addr, typestr(cp.addr.type));
  2541. if (mgmt_send(mgmt, MGMT_OP_PAIR_DEVICE, index, sizeof(cp), &cp,
  2542. pair_rsp, NULL, NULL) == 0) {
  2543. error("Unable to send pair_device cmd");
  2544. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2545. }
  2546. }
  2547. static void cancel_pair_rsp(uint8_t status, uint16_t len, const void *param,
  2548. void *user_data)
  2549. {
  2550. const struct mgmt_addr_info *rp = param;
  2551. char addr[18];
  2552. if (len == 0 && status != 0) {
  2553. error("Cancel Pairing failed with 0x%02x (%s)",
  2554. status, mgmt_errstr(status));
  2555. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2556. }
  2557. if (len != sizeof(*rp)) {
  2558. error("Unexpected cancel_pair_rsp len %u", len);
  2559. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2560. }
  2561. ba2str(&rp->bdaddr, addr);
  2562. if (status)
  2563. error("Cancel Pairing with %s (%s) failed. 0x%02x (%s)",
  2564. addr, typestr(rp->type), status,
  2565. mgmt_errstr(status));
  2566. else
  2567. print("Pairing Cancelled with %s", addr);
  2568. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2569. }
  2570. static struct option cancel_pair_options[] = {
  2571. { "help", 0, 0, 'h' },
  2572. { "type", 1, 0, 't' },
  2573. { 0, 0, 0, 0 }
  2574. };
  2575. static void cmd_cancel_pair(int argc, char **argv)
  2576. {
  2577. struct mgmt_addr_info cp;
  2578. uint8_t type = BDADDR_BREDR;
  2579. int opt;
  2580. uint16_t index;
  2581. while ((opt = getopt_long(argc, argv, "+t:h", cancel_pair_options,
  2582. NULL)) != -1) {
  2583. switch (opt) {
  2584. case 't':
  2585. type = strtol(optarg, NULL, 0);
  2586. break;
  2587. case 'h':
  2588. bt_shell_usage();
  2589. optind = 0;
  2590. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2591. default:
  2592. bt_shell_usage();
  2593. optind = 0;
  2594. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2595. }
  2596. }
  2597. argc -= optind;
  2598. argv += optind;
  2599. optind = 0;
  2600. if (argc < 1) {
  2601. bt_shell_usage();
  2602. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2603. }
  2604. index = mgmt_index;
  2605. if (index == MGMT_INDEX_NONE)
  2606. index = 0;
  2607. memset(&cp, 0, sizeof(cp));
  2608. str2ba(argv[0], &cp.bdaddr);
  2609. cp.type = type;
  2610. if (mgmt_reply(mgmt, MGMT_OP_CANCEL_PAIR_DEVICE, index, sizeof(cp), &cp,
  2611. cancel_pair_rsp, NULL, NULL) == 0) {
  2612. error("Unable to send cancel_pair_device cmd");
  2613. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2614. }
  2615. }
  2616. static void unpair_rsp(uint8_t status, uint16_t len, const void *param,
  2617. void *user_data)
  2618. {
  2619. const struct mgmt_rp_unpair_device *rp = param;
  2620. char addr[18];
  2621. if (len == 0 && status != 0) {
  2622. error("Unpair device failed. status 0x%02x (%s)",
  2623. status, mgmt_errstr(status));
  2624. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2625. }
  2626. if (len != sizeof(*rp)) {
  2627. error("Unexpected unpair_device_rsp len %u", len);
  2628. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2629. }
  2630. ba2str(&rp->addr.bdaddr, addr);
  2631. if (status)
  2632. error("Unpairing %s failed. status 0x%02x (%s)",
  2633. addr, status, mgmt_errstr(status));
  2634. else
  2635. print("%s unpaired", addr);
  2636. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2637. }
  2638. static struct option unpair_options[] = {
  2639. { "help", 0, 0, 'h' },
  2640. { "type", 1, 0, 't' },
  2641. { 0, 0, 0, 0 }
  2642. };
  2643. static void cmd_unpair(int argc, char **argv)
  2644. {
  2645. struct mgmt_cp_unpair_device cp;
  2646. uint8_t type = BDADDR_BREDR;
  2647. int opt;
  2648. uint16_t index = mgmt_index;
  2649. while ((opt = getopt_long(argc, argv, "+t:h", unpair_options,
  2650. NULL)) != -1) {
  2651. switch (opt) {
  2652. case 't':
  2653. type = strtol(optarg, NULL, 0);
  2654. break;
  2655. case 'h':
  2656. bt_shell_usage();
  2657. optind = 0;
  2658. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2659. default:
  2660. bt_shell_usage();
  2661. optind = 0;
  2662. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2663. }
  2664. }
  2665. argc -= optind;
  2666. argv += optind;
  2667. optind = 0;
  2668. if (argc < 1) {
  2669. bt_shell_usage();
  2670. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2671. }
  2672. index = mgmt_index;
  2673. if (index == MGMT_INDEX_NONE)
  2674. index = 0;
  2675. memset(&cp, 0, sizeof(cp));
  2676. str2ba(argv[0], &cp.addr.bdaddr);
  2677. cp.addr.type = type;
  2678. cp.disconnect = 1;
  2679. if (mgmt_send(mgmt, MGMT_OP_UNPAIR_DEVICE, index, sizeof(cp), &cp,
  2680. unpair_rsp, NULL, NULL) == 0) {
  2681. error("Unable to send unpair_device cmd");
  2682. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2683. }
  2684. }
  2685. static void keys_rsp(uint8_t status, uint16_t len, const void *param,
  2686. void *user_data)
  2687. {
  2688. if (status != 0)
  2689. error("Load keys failed with status 0x%02x (%s)",
  2690. status, mgmt_errstr(status));
  2691. else
  2692. print("Keys successfully loaded");
  2693. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2694. }
  2695. static void cmd_keys(int argc, char **argv)
  2696. {
  2697. struct mgmt_cp_load_link_keys cp;
  2698. uint16_t index;
  2699. index = mgmt_index;
  2700. if (index == MGMT_INDEX_NONE)
  2701. index = 0;
  2702. memset(&cp, 0, sizeof(cp));
  2703. if (mgmt_send(mgmt, MGMT_OP_LOAD_LINK_KEYS, index, sizeof(cp), &cp,
  2704. keys_rsp, NULL, NULL) == 0) {
  2705. error("Unable to send load_keys cmd");
  2706. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2707. }
  2708. }
  2709. static void ltks_rsp(uint8_t status, uint16_t len, const void *param,
  2710. void *user_data)
  2711. {
  2712. if (status != 0)
  2713. error("Load keys failed with status 0x%02x (%s)",
  2714. status, mgmt_errstr(status));
  2715. else
  2716. print("Long term keys successfully loaded");
  2717. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2718. }
  2719. static void cmd_ltks(int argc, char **argv)
  2720. {
  2721. struct mgmt_cp_load_long_term_keys cp;
  2722. uint16_t index;
  2723. index = mgmt_index;
  2724. if (index == MGMT_INDEX_NONE)
  2725. index = 0;
  2726. memset(&cp, 0, sizeof(cp));
  2727. if (mgmt_send(mgmt, MGMT_OP_LOAD_LONG_TERM_KEYS, index, sizeof(cp), &cp,
  2728. ltks_rsp, NULL, NULL) == 0) {
  2729. error("Unable to send load_ltks cmd");
  2730. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2731. }
  2732. }
  2733. static void irks_rsp(uint8_t status, uint16_t len, const void *param,
  2734. void *user_data)
  2735. {
  2736. if (status != 0)
  2737. error("Load IRKs failed with status 0x%02x (%s)",
  2738. status, mgmt_errstr(status));
  2739. else
  2740. print("Identity Resolving Keys successfully loaded");
  2741. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2742. }
  2743. static struct option irks_options[] = {
  2744. { "help", 0, 0, 'h' },
  2745. { "local", 1, 0, 'l' },
  2746. { "file", 1, 0, 'f' },
  2747. { 0, 0, 0, 0 }
  2748. };
  2749. #define MAX_IRKS 4
  2750. static void cmd_irks(int argc, char **argv)
  2751. {
  2752. struct mgmt_cp_load_irks *cp;
  2753. uint8_t buf[sizeof(*cp) + 23 * MAX_IRKS];
  2754. uint16_t count, local_index;
  2755. char path[PATH_MAX];
  2756. int opt;
  2757. uint16_t index;
  2758. index = mgmt_index;
  2759. if (index == MGMT_INDEX_NONE)
  2760. index = 0;
  2761. cp = (void *) buf;
  2762. count = 0;
  2763. while ((opt = getopt_long(argc, argv, "+l:f:h",
  2764. irks_options, NULL)) != -1) {
  2765. switch (opt) {
  2766. case 'l':
  2767. if (count >= MAX_IRKS) {
  2768. error("Number of IRKs exceeded");
  2769. optind = 0;
  2770. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2771. }
  2772. if (strlen(optarg) > 3 &&
  2773. strncasecmp(optarg, "hci", 3) == 0)
  2774. local_index = atoi(optarg + 3);
  2775. else
  2776. local_index = atoi(optarg);
  2777. snprintf(path, sizeof(path),
  2778. "/sys/kernel/debug/bluetooth/hci%u/identity",
  2779. local_index);
  2780. if (!load_identity(path, &cp->irks[count])) {
  2781. error("Unable to load identity");
  2782. optind = 0;
  2783. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2784. }
  2785. count++;
  2786. break;
  2787. case 'f':
  2788. if (count >= MAX_IRKS) {
  2789. error("Number of IRKs exceeded");
  2790. optind = 0;
  2791. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2792. }
  2793. if (!load_identity(optarg, &cp->irks[count])) {
  2794. error("Unable to load identities");
  2795. optind = 0;
  2796. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2797. }
  2798. count++;
  2799. break;
  2800. case 'h':
  2801. bt_shell_usage();
  2802. optind = 0;
  2803. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2804. default:
  2805. bt_shell_usage();
  2806. optind = 0;
  2807. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2808. }
  2809. }
  2810. argc -= optind;
  2811. argv += optind;
  2812. optind = 0;
  2813. cp->irk_count = cpu_to_le16(count);
  2814. if (mgmt_send(mgmt, MGMT_OP_LOAD_IRKS, index,
  2815. sizeof(*cp) + count * 23, cp,
  2816. irks_rsp, NULL, NULL) == 0) {
  2817. error("Unable to send load_irks cmd");
  2818. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2819. }
  2820. }
  2821. static void block_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
  2822. const void *param)
  2823. {
  2824. const struct mgmt_addr_info *rp = param;
  2825. char addr[18];
  2826. if (len == 0 && status != 0) {
  2827. error("%s failed, status 0x%02x (%s)",
  2828. mgmt_opstr(op), status, mgmt_errstr(status));
  2829. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2830. }
  2831. if (len != sizeof(*rp)) {
  2832. error("Unexpected %s len %u", mgmt_opstr(op), len);
  2833. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2834. }
  2835. ba2str(&rp->bdaddr, addr);
  2836. if (status)
  2837. error("%s %s (%s) failed. status 0x%02x (%s)",
  2838. mgmt_opstr(op), addr, typestr(rp->type),
  2839. status, mgmt_errstr(status));
  2840. else
  2841. print("%s %s succeeded", mgmt_opstr(op), addr);
  2842. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2843. }
  2844. static struct option block_options[] = {
  2845. { "help", 0, 0, 'h' },
  2846. { "type", 1, 0, 't' },
  2847. { 0, 0, 0, 0 }
  2848. };
  2849. static void cmd_block(int argc, char **argv)
  2850. {
  2851. struct mgmt_cp_block_device cp;
  2852. uint8_t type = BDADDR_BREDR;
  2853. int opt;
  2854. uint16_t index;
  2855. while ((opt = getopt_long(argc, argv, "+t:h", block_options,
  2856. NULL)) != -1) {
  2857. switch (opt) {
  2858. case 't':
  2859. type = strtol(optarg, NULL, 0);
  2860. break;
  2861. case 'h':
  2862. bt_shell_usage();
  2863. optind = 0;
  2864. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2865. default:
  2866. bt_shell_usage();
  2867. optind = 0;
  2868. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2869. }
  2870. }
  2871. argc -= optind;
  2872. argv += optind;
  2873. optind = 0;
  2874. if (argc < 1) {
  2875. bt_shell_usage();
  2876. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2877. }
  2878. index = mgmt_index;
  2879. if (index == MGMT_INDEX_NONE)
  2880. index = 0;
  2881. memset(&cp, 0, sizeof(cp));
  2882. str2ba(argv[0], &cp.addr.bdaddr);
  2883. cp.addr.type = type;
  2884. if (send_cmd(mgmt, MGMT_OP_BLOCK_DEVICE, index, sizeof(cp), &cp,
  2885. block_rsp) == 0) {
  2886. error("Unable to send block_device cmd");
  2887. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2888. }
  2889. }
  2890. static void cmd_unblock(int argc, char **argv)
  2891. {
  2892. struct mgmt_cp_unblock_device cp;
  2893. uint8_t type = BDADDR_BREDR;
  2894. int opt;
  2895. uint16_t index;
  2896. while ((opt = getopt_long(argc, argv, "+t:h", block_options,
  2897. NULL)) != -1) {
  2898. switch (opt) {
  2899. case 't':
  2900. type = strtol(optarg, NULL, 0);
  2901. break;
  2902. case 'h':
  2903. bt_shell_usage();
  2904. optind = 0;
  2905. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  2906. default:
  2907. bt_shell_usage();
  2908. optind = 0;
  2909. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2910. }
  2911. }
  2912. argc -= optind;
  2913. argv += optind;
  2914. optind = 0;
  2915. if (argc < 1) {
  2916. bt_shell_usage();
  2917. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2918. }
  2919. index = mgmt_index;
  2920. if (index == MGMT_INDEX_NONE)
  2921. index = 0;
  2922. memset(&cp, 0, sizeof(cp));
  2923. str2ba(argv[0], &cp.addr.bdaddr);
  2924. cp.addr.type = type;
  2925. if (send_cmd(mgmt, MGMT_OP_UNBLOCK_DEVICE, index, sizeof(cp), &cp,
  2926. block_rsp) == 0) {
  2927. error("Unable to send unblock_device cmd");
  2928. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2929. }
  2930. }
  2931. static void cmd_add_uuid(int argc, char **argv)
  2932. {
  2933. struct mgmt_cp_add_uuid cp;
  2934. uint128_t uint128;
  2935. uuid_t uuid, uuid128;
  2936. uint16_t index;
  2937. if (argc < 3) {
  2938. print("UUID and service hint needed");
  2939. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2940. }
  2941. index = mgmt_index;
  2942. if (index == MGMT_INDEX_NONE)
  2943. index = 0;
  2944. if (bt_string2uuid(&uuid, argv[1]) < 0) {
  2945. print("Invalid UUID: %s", argv[1]);
  2946. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2947. }
  2948. memset(&cp, 0, sizeof(cp));
  2949. uuid_to_uuid128(&uuid128, &uuid);
  2950. ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
  2951. htob128(&uint128, (uint128_t *) cp.uuid);
  2952. cp.svc_hint = atoi(argv[2]);
  2953. if (send_cmd(mgmt, MGMT_OP_ADD_UUID, index, sizeof(cp), &cp,
  2954. class_rsp) == 0) {
  2955. error("Unable to send add_uuid cmd");
  2956. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2957. }
  2958. }
  2959. static void cmd_remove_uuid(int argc, char **argv)
  2960. {
  2961. struct mgmt_cp_remove_uuid cp;
  2962. uint128_t uint128;
  2963. uuid_t uuid, uuid128;
  2964. uint16_t index;
  2965. if (argc < 2) {
  2966. print("UUID needed");
  2967. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2968. }
  2969. index = mgmt_index;
  2970. if (index == MGMT_INDEX_NONE)
  2971. index = 0;
  2972. if (bt_string2uuid(&uuid, argv[1]) < 0) {
  2973. print("Invalid UUID: %s", argv[1]);
  2974. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2975. }
  2976. memset(&cp, 0, sizeof(cp));
  2977. uuid_to_uuid128(&uuid128, &uuid);
  2978. ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
  2979. htob128(&uint128, (uint128_t *) cp.uuid);
  2980. if (send_cmd(mgmt, MGMT_OP_REMOVE_UUID, index, sizeof(cp), &cp,
  2981. class_rsp) == 0) {
  2982. error("Unable to send remove_uuid cmd");
  2983. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  2984. }
  2985. }
  2986. static void cmd_clr_uuids(int argc, char **argv)
  2987. {
  2988. char *uuid_any = "00000000-0000-0000-0000-000000000000";
  2989. char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
  2990. cmd_remove_uuid(2, rm_argv);
  2991. }
  2992. static void local_oob_rsp(uint8_t status, uint16_t len, const void *param,
  2993. void *user_data)
  2994. {
  2995. const struct mgmt_rp_read_local_oob_data *rp = param;
  2996. char str[33];
  2997. if (status != 0) {
  2998. error("Read Local OOB Data failed with status 0x%02x (%s)",
  2999. status, mgmt_errstr(status));
  3000. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3001. }
  3002. if (len < sizeof(*rp)) {
  3003. error("Too small (%u bytes) read_local_oob rsp", len);
  3004. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3005. }
  3006. bin2hex(rp->hash192, 16, str, sizeof(str));
  3007. print("Hash C from P-192: %s", str);
  3008. bin2hex(rp->rand192, 16, str, sizeof(str));
  3009. print("Randomizer R with P-192: %s", str);
  3010. if (len < sizeof(*rp))
  3011. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3012. bin2hex(rp->hash256, 16, str, sizeof(str));
  3013. print("Hash C from P-256: %s", str);
  3014. bin2hex(rp->rand256, 16, str, sizeof(str));
  3015. print("Randomizer R with P-256: %s", str);
  3016. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3017. }
  3018. static void cmd_local_oob(int argc, char **argv)
  3019. {
  3020. uint16_t index;
  3021. index = mgmt_index;
  3022. if (index == MGMT_INDEX_NONE)
  3023. index = 0;
  3024. if (mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_DATA, index, 0, NULL,
  3025. local_oob_rsp, NULL, NULL) == 0) {
  3026. error("Unable to send read_local_oob cmd");
  3027. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3028. }
  3029. }
  3030. static void remote_oob_rsp(uint8_t status, uint16_t len, const void *param,
  3031. void *user_data)
  3032. {
  3033. const struct mgmt_addr_info *rp = param;
  3034. char addr[18];
  3035. if (status != 0) {
  3036. error("Add Remote OOB Data failed: 0x%02x (%s)",
  3037. status, mgmt_errstr(status));
  3038. return;
  3039. }
  3040. if (len < sizeof(*rp)) {
  3041. error("Too small (%u bytes) add_remote_oob rsp", len);
  3042. return;
  3043. }
  3044. ba2str(&rp->bdaddr, addr);
  3045. print("Remote OOB data added for %s (%u)", addr, rp->type);
  3046. }
  3047. static struct option remote_oob_opt[] = {
  3048. { "help", 0, 0, '?' },
  3049. { "type", 1, 0, 't' },
  3050. { 0, 0, 0, 0 }
  3051. };
  3052. static void cmd_remote_oob(int argc, char **argv)
  3053. {
  3054. struct mgmt_cp_add_remote_oob_data cp;
  3055. int opt;
  3056. uint16_t index;
  3057. memset(&cp, 0, sizeof(cp));
  3058. cp.addr.type = BDADDR_BREDR;
  3059. while ((opt = getopt_long(argc, argv, "+t:r:R:h:H:",
  3060. remote_oob_opt, NULL)) != -1) {
  3061. switch (opt) {
  3062. case 't':
  3063. cp.addr.type = strtol(optarg, NULL, 0);
  3064. break;
  3065. case 'r':
  3066. hex2bin(optarg, cp.rand192, 16);
  3067. break;
  3068. case 'h':
  3069. hex2bin(optarg, cp.hash192, 16);
  3070. break;
  3071. case 'R':
  3072. hex2bin(optarg, cp.rand256, 16);
  3073. break;
  3074. case 'H':
  3075. hex2bin(optarg, cp.hash256, 16);
  3076. break;
  3077. default:
  3078. bt_shell_usage();
  3079. optind = 0;
  3080. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3081. }
  3082. }
  3083. argc -= optind;
  3084. argv += optind;
  3085. optind = 0;
  3086. if (argc < 1) {
  3087. bt_shell_usage();
  3088. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3089. }
  3090. index = mgmt_index;
  3091. if (index == MGMT_INDEX_NONE)
  3092. index = 0;
  3093. str2ba(argv[0], &cp.addr.bdaddr);
  3094. print("Adding OOB data for %s (%s)", argv[0], typestr(cp.addr.type));
  3095. if (mgmt_send(mgmt, MGMT_OP_ADD_REMOTE_OOB_DATA, index,
  3096. sizeof(cp), &cp, remote_oob_rsp,
  3097. NULL, NULL) == 0) {
  3098. error("Unable to send add_remote_oob cmd");
  3099. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3100. }
  3101. }
  3102. static void did_rsp(uint8_t status, uint16_t len, const void *param,
  3103. void *user_data)
  3104. {
  3105. if (status != 0)
  3106. error("Set Device ID failed with status 0x%02x (%s)",
  3107. status, mgmt_errstr(status));
  3108. else
  3109. print("Device ID successfully set");
  3110. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3111. }
  3112. static void cmd_did(int argc, char **argv)
  3113. {
  3114. struct mgmt_cp_set_device_id cp;
  3115. uint16_t vendor, product, version , source;
  3116. int result;
  3117. uint16_t index;
  3118. result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
  3119. &version);
  3120. if (result == 3) {
  3121. source = 0x0001;
  3122. goto done;
  3123. }
  3124. result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
  3125. &version);
  3126. if (result == 3) {
  3127. source = 0x0002;
  3128. goto done;
  3129. }
  3130. return;
  3131. done:
  3132. index = mgmt_index;
  3133. if (index == MGMT_INDEX_NONE)
  3134. index = 0;
  3135. cp.source = htobs(source);
  3136. cp.vendor = htobs(vendor);
  3137. cp.product = htobs(product);
  3138. cp.version = htobs(version);
  3139. if (mgmt_send(mgmt, MGMT_OP_SET_DEVICE_ID, index, sizeof(cp), &cp,
  3140. did_rsp, NULL, NULL) == 0) {
  3141. error("Unable to send set_device_id cmd");
  3142. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3143. }
  3144. }
  3145. static void static_addr_rsp(uint8_t status, uint16_t len, const void *param,
  3146. void *user_data)
  3147. {
  3148. if (status != 0)
  3149. error("Set static address failed with status 0x%02x (%s)",
  3150. status, mgmt_errstr(status));
  3151. else
  3152. print("Static address successfully set");
  3153. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3154. }
  3155. static void cmd_static_addr(int argc, char **argv)
  3156. {
  3157. struct mgmt_cp_set_static_address cp;
  3158. uint16_t index;
  3159. index = mgmt_index;
  3160. if (index == MGMT_INDEX_NONE)
  3161. index = 0;
  3162. str2ba(argv[1], &cp.bdaddr);
  3163. if (mgmt_send(mgmt, MGMT_OP_SET_STATIC_ADDRESS, index, sizeof(cp), &cp,
  3164. static_addr_rsp, NULL, NULL) == 0) {
  3165. error("Unable to send set_static_address cmd");
  3166. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3167. }
  3168. }
  3169. static void options_rsp(uint16_t op, uint16_t id, uint8_t status,
  3170. uint16_t len, const void *param)
  3171. {
  3172. const uint32_t *rp = param;
  3173. if (status != 0) {
  3174. error("%s for hci%u failed with status 0x%02x (%s)",
  3175. mgmt_opstr(op), id, status, mgmt_errstr(status));
  3176. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3177. }
  3178. if (len < sizeof(*rp)) {
  3179. error("Too small %s response (%u bytes)",
  3180. mgmt_opstr(op), len);
  3181. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3182. }
  3183. print("hci%u %s complete, options: %s", id, mgmt_opstr(op),
  3184. options2str(get_le32(rp)));
  3185. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3186. }
  3187. static void cmd_public_addr(int argc, char **argv)
  3188. {
  3189. struct mgmt_cp_set_public_address cp;
  3190. uint16_t index;
  3191. index = mgmt_index;
  3192. if (index == MGMT_INDEX_NONE)
  3193. index = 0;
  3194. str2ba(argv[1], &cp.bdaddr);
  3195. if (send_cmd(mgmt, MGMT_OP_SET_PUBLIC_ADDRESS, index, sizeof(cp), &cp,
  3196. options_rsp) == 0) {
  3197. error("Unable to send Set Public Address cmd");
  3198. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3199. }
  3200. }
  3201. static void cmd_ext_config(int argc, char **argv)
  3202. {
  3203. struct mgmt_cp_set_external_config cp;
  3204. uint16_t index;
  3205. if (parse_setting(argc, argv, &cp.config) == false)
  3206. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3207. index = mgmt_index;
  3208. if (index == MGMT_INDEX_NONE)
  3209. index = 0;
  3210. if (send_cmd(mgmt, MGMT_OP_SET_EXTERNAL_CONFIG, index, sizeof(cp), &cp,
  3211. options_rsp) == 0) {
  3212. error("Unable to send Set External Config cmd");
  3213. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3214. }
  3215. }
  3216. static void cmd_debug_keys(int argc, char **argv)
  3217. {
  3218. cmd_setting(MGMT_OP_SET_DEBUG_KEYS, argc, argv);
  3219. }
  3220. static void conn_info_rsp(uint8_t status, uint16_t len, const void *param,
  3221. void *user_data)
  3222. {
  3223. const struct mgmt_rp_get_conn_info *rp = param; char addr[18];
  3224. if (len == 0 && status != 0) {
  3225. error("Get Conn Info failed, status 0x%02x (%s)",
  3226. status, mgmt_errstr(status));
  3227. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3228. }
  3229. if (len < sizeof(*rp)) {
  3230. error("Unexpected Get Conn Info len %u", len);
  3231. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3232. }
  3233. ba2str(&rp->addr.bdaddr, addr);
  3234. if (status) {
  3235. error("Get Conn Info for %s (%s) failed. status 0x%02x (%s)",
  3236. addr, typestr(rp->addr.type),
  3237. status, mgmt_errstr(status));
  3238. } else {
  3239. print("Connection Information for %s (%s)",
  3240. addr, typestr(rp->addr.type));
  3241. print("\tRSSI %d\tTX power %d\tmaximum TX power %d",
  3242. rp->rssi, rp->tx_power, rp->max_tx_power);
  3243. }
  3244. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3245. }
  3246. static struct option conn_info_options[] = {
  3247. { "help", 0, 0, 'h' },
  3248. { "type", 1, 0, 't' },
  3249. { 0, 0, 0, 0 }
  3250. };
  3251. static void cmd_conn_info(int argc, char **argv)
  3252. {
  3253. struct mgmt_cp_get_conn_info cp;
  3254. uint8_t type = BDADDR_BREDR;
  3255. int opt;
  3256. uint16_t index;
  3257. while ((opt = getopt_long(argc, argv, "+t:h", conn_info_options,
  3258. NULL)) != -1) {
  3259. switch (opt) {
  3260. case 't':
  3261. type = strtol(optarg, NULL, 0);
  3262. break;
  3263. case 'h':
  3264. bt_shell_usage();
  3265. optind = 0;
  3266. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3267. default:
  3268. bt_shell_usage();
  3269. optind = 0;
  3270. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3271. }
  3272. }
  3273. argc -= optind;
  3274. argv += optind;
  3275. optind = 0;
  3276. if (argc < 1) {
  3277. bt_shell_usage();
  3278. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3279. }
  3280. index = mgmt_index;
  3281. if (index == MGMT_INDEX_NONE)
  3282. index = 0;
  3283. memset(&cp, 0, sizeof(cp));
  3284. str2ba(argv[0], &cp.addr.bdaddr);
  3285. cp.addr.type = type;
  3286. if (mgmt_send(mgmt, MGMT_OP_GET_CONN_INFO, index, sizeof(cp), &cp,
  3287. conn_info_rsp, NULL, NULL) == 0) {
  3288. error("Unable to send get_conn_info cmd");
  3289. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3290. }
  3291. }
  3292. static void io_cap_rsp(uint8_t status, uint16_t len, const void *param,
  3293. void *user_data)
  3294. {
  3295. if (status != 0)
  3296. error("Could not set IO Capability with status 0x%02x (%s)",
  3297. status, mgmt_errstr(status));
  3298. else
  3299. print("IO Capabilities successfully set");
  3300. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3301. }
  3302. static void cmd_io_cap(int argc, char **argv)
  3303. {
  3304. struct mgmt_cp_set_io_capability cp;
  3305. uint8_t cap;
  3306. uint16_t index;
  3307. index = mgmt_index;
  3308. if (index == MGMT_INDEX_NONE)
  3309. index = 0;
  3310. cap = strtol(argv[1], NULL, 0);
  3311. memset(&cp, 0, sizeof(cp));
  3312. cp.io_capability = cap;
  3313. if (mgmt_send(mgmt, MGMT_OP_SET_IO_CAPABILITY, index, sizeof(cp), &cp,
  3314. io_cap_rsp, NULL, NULL) == 0) {
  3315. error("Unable to send set-io-cap cmd");
  3316. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3317. }
  3318. }
  3319. static void scan_params_rsp(uint8_t status, uint16_t len, const void *param,
  3320. void *user_data)
  3321. {
  3322. if (status != 0)
  3323. error("Set scan parameters failed with status 0x%02x (%s)",
  3324. status, mgmt_errstr(status));
  3325. else
  3326. print("Scan parameters successfully set");
  3327. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3328. }
  3329. static void cmd_scan_params(int argc, char **argv)
  3330. {
  3331. struct mgmt_cp_set_scan_params cp;
  3332. uint16_t index;
  3333. index = mgmt_index;
  3334. if (index == MGMT_INDEX_NONE)
  3335. index = 0;
  3336. cp.interval = strtol(argv[1], NULL, 0);
  3337. cp.window = strtol(argv[2], NULL, 0);
  3338. if (mgmt_send(mgmt, MGMT_OP_SET_SCAN_PARAMS, index, sizeof(cp), &cp,
  3339. scan_params_rsp, NULL, NULL) == 0) {
  3340. error("Unable to send set_scan_params cmd");
  3341. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3342. }
  3343. }
  3344. static void clock_info_rsp(uint8_t status, uint16_t len, const void *param,
  3345. void *user_data)
  3346. {
  3347. const struct mgmt_rp_get_clock_info *rp = param;
  3348. if (len < sizeof(*rp)) {
  3349. error("Unexpected Get Clock Info len %u", len);
  3350. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3351. }
  3352. if (status) {
  3353. error("Get Clock Info failed with status 0x%02x (%s)",
  3354. status, mgmt_errstr(status));
  3355. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3356. }
  3357. print("Local Clock: %u", le32_to_cpu(rp->local_clock));
  3358. print("Piconet Clock: %u", le32_to_cpu(rp->piconet_clock));
  3359. print("Accurary: %u", le16_to_cpu(rp->accuracy));
  3360. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3361. }
  3362. static void cmd_clock_info(int argc, char **argv)
  3363. {
  3364. struct mgmt_cp_get_clock_info cp;
  3365. uint16_t index;
  3366. index = mgmt_index;
  3367. if (index == MGMT_INDEX_NONE)
  3368. index = 0;
  3369. memset(&cp, 0, sizeof(cp));
  3370. if (argc > 1)
  3371. str2ba(argv[1], &cp.addr.bdaddr);
  3372. if (mgmt_send(mgmt, MGMT_OP_GET_CLOCK_INFO, index, sizeof(cp), &cp,
  3373. clock_info_rsp, NULL, NULL) == 0) {
  3374. error("Unable to send get_clock_info cmd");
  3375. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3376. }
  3377. }
  3378. static void add_device_rsp(uint8_t status, uint16_t len, const void *param,
  3379. void *user_data)
  3380. {
  3381. if (status != 0)
  3382. error("Add device failed with status 0x%02x (%s)",
  3383. status, mgmt_errstr(status));
  3384. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3385. }
  3386. static struct option add_device_options[] = {
  3387. { "help", 0, 0, 'h' },
  3388. { "action", 1, 0, 'a' },
  3389. { "type", 1, 0, 't' },
  3390. { 0, 0, 0, 0 }
  3391. };
  3392. static void cmd_add_device(int argc, char **argv)
  3393. {
  3394. struct mgmt_cp_add_device cp;
  3395. uint8_t action = 0x00;
  3396. uint8_t type = BDADDR_BREDR;
  3397. char addr[18];
  3398. int opt;
  3399. uint16_t index;
  3400. while ((opt = getopt_long(argc, argv, "+a:t:h", add_device_options,
  3401. NULL)) != -1) {
  3402. switch (opt) {
  3403. case 'a':
  3404. action = strtol(optarg, NULL, 0);
  3405. break;
  3406. case 't':
  3407. type = strtol(optarg, NULL, 0);
  3408. break;
  3409. case 'h':
  3410. bt_shell_usage();
  3411. optind = 0;
  3412. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3413. default:
  3414. bt_shell_usage();
  3415. optind = 0;
  3416. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3417. }
  3418. }
  3419. argc -= optind;
  3420. argv += optind;
  3421. optind = 0;
  3422. if (argc < 1) {
  3423. bt_shell_usage();
  3424. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3425. }
  3426. index = mgmt_index;
  3427. if (index == MGMT_INDEX_NONE)
  3428. index = 0;
  3429. memset(&cp, 0, sizeof(cp));
  3430. str2ba(argv[0], &cp.addr.bdaddr);
  3431. cp.addr.type = type;
  3432. cp.action = action;
  3433. ba2str(&cp.addr.bdaddr, addr);
  3434. print("Adding device with %s (%s)", addr, typestr(cp.addr.type));
  3435. if (mgmt_send(mgmt, MGMT_OP_ADD_DEVICE, index, sizeof(cp), &cp,
  3436. add_device_rsp, NULL, NULL) == 0) {
  3437. error("Unable to send add device command");
  3438. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3439. }
  3440. }
  3441. static void remove_device_rsp(uint8_t status, uint16_t len, const void *param,
  3442. void *user_data)
  3443. {
  3444. if (status != 0)
  3445. error("Remove device failed with status 0x%02x (%s)",
  3446. status, mgmt_errstr(status));
  3447. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3448. }
  3449. static struct option del_device_options[] = {
  3450. { "help", 0, 0, 'h' },
  3451. { "type", 1, 0, 't' },
  3452. { 0, 0, 0, 0 }
  3453. };
  3454. static void cmd_del_device(int argc, char **argv)
  3455. {
  3456. struct mgmt_cp_remove_device cp;
  3457. uint8_t type = BDADDR_BREDR;
  3458. char addr[18];
  3459. int opt;
  3460. uint16_t index;
  3461. while ((opt = getopt_long(argc, argv, "+t:h", del_device_options,
  3462. NULL)) != -1) {
  3463. switch (opt) {
  3464. case 't':
  3465. type = strtol(optarg, NULL, 0);
  3466. break;
  3467. case 'h':
  3468. bt_shell_usage();
  3469. optind = 0;
  3470. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3471. default:
  3472. bt_shell_usage();
  3473. optind = 0;
  3474. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3475. }
  3476. }
  3477. argc -= optind;
  3478. argv += optind;
  3479. optind = 0;
  3480. if (argc < 1) {
  3481. bt_shell_usage();
  3482. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3483. }
  3484. index = mgmt_index;
  3485. if (index == MGMT_INDEX_NONE)
  3486. index = 0;
  3487. memset(&cp, 0, sizeof(cp));
  3488. str2ba(argv[0], &cp.addr.bdaddr);
  3489. cp.addr.type = type;
  3490. ba2str(&cp.addr.bdaddr, addr);
  3491. print("Removing device with %s (%s)", addr, typestr(cp.addr.type));
  3492. if (mgmt_send(mgmt, MGMT_OP_REMOVE_DEVICE, index, sizeof(cp), &cp,
  3493. remove_device_rsp, NULL, NULL) == 0) {
  3494. error("Unable to send remove device command");
  3495. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3496. }
  3497. }
  3498. static void cmd_clr_devices(int argc, char **argv)
  3499. {
  3500. char *bdaddr_any = "00:00:00:00:00:00";
  3501. char *rm_argv[] = { "del-device", bdaddr_any, NULL };
  3502. cmd_del_device(2, rm_argv);
  3503. }
  3504. static void local_oob_ext_rsp(uint8_t status, uint16_t len, const void *param,
  3505. void *user_data)
  3506. {
  3507. const struct mgmt_rp_read_local_oob_ext_data *rp = param;
  3508. uint16_t eir_len;
  3509. if (status != 0) {
  3510. error("Read Local OOB Ext Data failed with status 0x%02x (%s)",
  3511. status, mgmt_errstr(status));
  3512. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3513. }
  3514. if (len < sizeof(*rp)) {
  3515. error("Too small (%u bytes) read_local_oob_ext rsp", len);
  3516. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3517. }
  3518. eir_len = le16_to_cpu(rp->eir_len);
  3519. if (len != sizeof(*rp) + eir_len) {
  3520. error("local_oob_ext: expected %zu bytes, got %u bytes",
  3521. sizeof(*rp) + eir_len, len);
  3522. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3523. }
  3524. print_eir(rp->eir, eir_len);
  3525. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3526. }
  3527. static void cmd_bredr_oob(int argc, char **argv)
  3528. {
  3529. struct mgmt_cp_read_local_oob_ext_data cp;
  3530. uint16_t index;
  3531. index = mgmt_index;
  3532. if (index == MGMT_INDEX_NONE)
  3533. index = 0;
  3534. cp.type = SCAN_TYPE_BREDR;
  3535. if (!mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
  3536. index, sizeof(cp), &cp,
  3537. local_oob_ext_rsp, NULL, NULL)) {
  3538. error("Unable to send read_local_oob_ext cmd");
  3539. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3540. }
  3541. }
  3542. static void cmd_le_oob(int argc, char **argv)
  3543. {
  3544. struct mgmt_cp_read_local_oob_ext_data cp;
  3545. uint16_t index;
  3546. index = mgmt_index;
  3547. if (index == MGMT_INDEX_NONE)
  3548. index = 0;
  3549. cp.type = SCAN_TYPE_LE;
  3550. if (!mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
  3551. index, sizeof(cp), &cp,
  3552. local_oob_ext_rsp, NULL, NULL)) {
  3553. error("Unable to send read_local_oob_ext cmd");
  3554. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3555. }
  3556. }
  3557. static const char *adv_flags_str[] = {
  3558. "connectable",
  3559. "general-discoverable",
  3560. "limited-discoverable",
  3561. "managed-flags",
  3562. "tx-power",
  3563. "scan-rsp-appearance",
  3564. "scan-rsp-local-name",
  3565. "Secondary-channel-1M",
  3566. "Secondary-channel-2M",
  3567. "Secondary-channel-CODED",
  3568. };
  3569. static const char *adv_flags2str(uint32_t flags)
  3570. {
  3571. static char str[256];
  3572. unsigned i;
  3573. int off;
  3574. off = 0;
  3575. str[0] = '\0';
  3576. for (i = 0; i < NELEM(adv_flags_str); i++) {
  3577. if ((flags & (1 << i)) != 0)
  3578. off += snprintf(str + off, sizeof(str) - off, "%s ",
  3579. adv_flags_str[i]);
  3580. }
  3581. return str;
  3582. }
  3583. static void adv_features_rsp(uint8_t status, uint16_t len, const void *param,
  3584. void *user_data)
  3585. {
  3586. const struct mgmt_rp_read_adv_features *rp = param;
  3587. uint32_t supported_flags;
  3588. if (status != 0) {
  3589. error("Reading adv features failed with status 0x%02x (%s)",
  3590. status, mgmt_errstr(status));
  3591. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3592. }
  3593. if (len < sizeof(*rp)) {
  3594. error("Too small adv features reply (%u bytes)", len);
  3595. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3596. }
  3597. if (len < sizeof(*rp) + rp->num_instances * sizeof(uint8_t)) {
  3598. error("Instances count (%u) doesn't match reply length (%u)",
  3599. rp->num_instances, len);
  3600. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3601. }
  3602. supported_flags = le32_to_cpu(rp->supported_flags);
  3603. print("Supported flags: %s", adv_flags2str(supported_flags));
  3604. print("Max advertising data len: %u", rp->max_adv_data_len);
  3605. print("Max scan response data len: %u", rp->max_scan_rsp_len);
  3606. print("Max instances: %u", rp->max_instances);
  3607. print("Instances list with %u item%s", rp->num_instances,
  3608. rp->num_instances != 1 ? "s" : "");
  3609. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3610. }
  3611. static void cmd_advinfo(int argc, char **argv)
  3612. {
  3613. uint16_t index;
  3614. index = mgmt_index;
  3615. if (index == MGMT_INDEX_NONE)
  3616. index = 0;
  3617. if (!mgmt_send(mgmt, MGMT_OP_READ_ADV_FEATURES, index, 0, NULL,
  3618. adv_features_rsp, NULL, NULL)) {
  3619. error("Unable to send advertising features command");
  3620. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3621. }
  3622. }
  3623. static void adv_size_info_rsp(uint8_t status, uint16_t len, const void *param,
  3624. void *user_data)
  3625. {
  3626. const struct mgmt_rp_get_adv_size_info *rp = param;
  3627. uint32_t flags;
  3628. if (status != 0) {
  3629. error("Reading adv size info failed with status 0x%02x (%s)",
  3630. status, mgmt_errstr(status));
  3631. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3632. }
  3633. if (len < sizeof(*rp)) {
  3634. error("Too small adv size info reply (%u bytes)", len);
  3635. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3636. }
  3637. flags = le32_to_cpu(rp->flags);
  3638. print("Instance: %u", rp->instance);
  3639. print("Flags: %s", adv_flags2str(flags));
  3640. print("Max advertising data len: %u", rp->max_adv_data_len);
  3641. print("Max scan response data len: %u", rp->max_scan_rsp_len);
  3642. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3643. }
  3644. static void advsize_usage(void)
  3645. {
  3646. bt_shell_usage();
  3647. print("Options:\n"
  3648. "\t -c, --connectable \"connectable\" flag\n"
  3649. "\t -g, --general-discov \"general-discoverable\" flag\n"
  3650. "\t -l, --limited-discov \"limited-discoverable\" flag\n"
  3651. "\t -m, --managed-flags \"managed-flags\" flag\n"
  3652. "\t -p, --tx-power \"tx-power\" flag\n"
  3653. "\t -a, --appearance \"appearance\" flag\n"
  3654. "\t -n, --local-name \"local-name\" flag");
  3655. }
  3656. static struct option advsize_options[] = {
  3657. { "help", 0, 0, 'h' },
  3658. { "connectable", 0, 0, 'c' },
  3659. { "general-discov", 0, 0, 'g' },
  3660. { "limited-discov", 0, 0, 'l' },
  3661. { "managed-flags", 0, 0, 'm' },
  3662. { "tx-power", 0, 0, 'p' },
  3663. { "appearance", 0, 0, 'a' },
  3664. { "local-name", 0, 0, 'n' },
  3665. { 0, 0, 0, 0}
  3666. };
  3667. static void cmd_advsize(int argc, char **argv)
  3668. {
  3669. struct mgmt_cp_get_adv_size_info cp;
  3670. uint8_t instance;
  3671. uint32_t flags = 0;
  3672. int opt;
  3673. uint16_t index;
  3674. while ((opt = getopt_long(argc, argv, "+cglmphna",
  3675. advsize_options, NULL)) != -1) {
  3676. switch (opt) {
  3677. case 'c':
  3678. flags |= MGMT_ADV_FLAG_CONNECTABLE;
  3679. break;
  3680. case 'g':
  3681. flags |= MGMT_ADV_FLAG_DISCOV;
  3682. break;
  3683. case 'l':
  3684. flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
  3685. break;
  3686. case 'm':
  3687. flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
  3688. break;
  3689. case 'p':
  3690. flags |= MGMT_ADV_FLAG_TX_POWER;
  3691. break;
  3692. case 'a':
  3693. flags |= MGMT_ADV_FLAG_APPEARANCE;
  3694. break;
  3695. case 'n':
  3696. flags |= MGMT_ADV_FLAG_LOCAL_NAME;
  3697. break;
  3698. default:
  3699. advsize_usage();
  3700. optind = 0;
  3701. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3702. }
  3703. }
  3704. argc -= optind;
  3705. argv += optind;
  3706. optind = 0;
  3707. if (argc != 1) {
  3708. advsize_usage();
  3709. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3710. }
  3711. instance = strtol(argv[0], NULL, 0);
  3712. index = mgmt_index;
  3713. if (index == MGMT_INDEX_NONE)
  3714. index = 0;
  3715. memset(&cp, 0, sizeof(cp));
  3716. cp.instance = instance;
  3717. cp.flags = cpu_to_le32(flags);
  3718. if (!mgmt_send(mgmt, MGMT_OP_GET_ADV_SIZE_INFO, index, sizeof(cp), &cp,
  3719. adv_size_info_rsp, NULL, NULL)) {
  3720. error("Unable to send advertising size info command");
  3721. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3722. }
  3723. }
  3724. static void add_adv_rsp(uint8_t status, uint16_t len, const void *param,
  3725. void *user_data)
  3726. {
  3727. const struct mgmt_rp_add_advertising *rp = param;
  3728. if (status != 0) {
  3729. error("Add Advertising failed with status 0x%02x (%s)",
  3730. status, mgmt_errstr(status));
  3731. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3732. }
  3733. if (len != sizeof(*rp)) {
  3734. error("Invalid Add Advertising response length (%u)", len);
  3735. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3736. }
  3737. print("Instance added: %u", rp->instance);
  3738. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3739. }
  3740. static void add_adv_usage(void)
  3741. {
  3742. bt_shell_usage();
  3743. print("Options:\n"
  3744. "\t -u, --uuid <uuid> Service UUID\n"
  3745. "\t -d, --adv-data <data> Advertising Data bytes\n"
  3746. "\t -s, --scan-rsp <data> Scan Response Data bytes\n"
  3747. "\t -t, --timeout <timeout> Timeout in seconds\n"
  3748. "\t -D, --duration <duration> Duration in seconds\n"
  3749. "\t -P, --phy <phy> Phy type, Specify 1M/2M/CODED\n"
  3750. "\t -c, --connectable \"connectable\" flag\n"
  3751. "\t -g, --general-discov \"general-discoverable\" flag\n"
  3752. "\t -l, --limited-discov \"limited-discoverable\" flag\n"
  3753. "\t -n, --scan-rsp-local-name \"local-name\" flag\n"
  3754. "\t -a, --scan-rsp-appearance \"appearance\" flag\n"
  3755. "\t -m, --managed-flags \"managed-flags\" flag\n"
  3756. "\t -p, --tx-power \"tx-power\" flag\n"
  3757. "e.g.:\n"
  3758. "\tadd-adv -u 180d -u 180f -d 080954657374204C45 1");
  3759. }
  3760. static struct option add_adv_options[] = {
  3761. { "help", 0, 0, 'h' },
  3762. { "uuid", 1, 0, 'u' },
  3763. { "adv-data", 1, 0, 'd' },
  3764. { "scan-rsp", 1, 0, 's' },
  3765. { "timeout", 1, 0, 't' },
  3766. { "duration", 1, 0, 'D' },
  3767. { "phy", 1, 0, 'P' },
  3768. { "connectable", 0, 0, 'c' },
  3769. { "general-discov", 0, 0, 'g' },
  3770. { "limited-discov", 0, 0, 'l' },
  3771. { "managed-flags", 0, 0, 'm' },
  3772. { "tx-power", 0, 0, 'p' },
  3773. { 0, 0, 0, 0}
  3774. };
  3775. static bool parse_bytes(char *optarg, uint8_t **bytes, size_t *len)
  3776. {
  3777. unsigned i;
  3778. if (!optarg) {
  3779. add_adv_usage();
  3780. return false;
  3781. }
  3782. *len = strlen(optarg);
  3783. if (*len % 2) {
  3784. error("Malformed data");
  3785. return false;
  3786. }
  3787. *len /= 2;
  3788. if (*len > UINT8_MAX) {
  3789. error("Data too long");
  3790. return false;
  3791. }
  3792. *bytes = malloc(*len);
  3793. if (!*bytes) {
  3794. error("Failed to allocate memory");
  3795. return false;
  3796. }
  3797. for (i = 0; i < *len; i++) {
  3798. if (sscanf(optarg + (i * 2), "%2hhx", *bytes + i) != 1) {
  3799. error("Invalid data");
  3800. free(*bytes);
  3801. *bytes = NULL;
  3802. return false;
  3803. }
  3804. }
  3805. return true;
  3806. }
  3807. #define MAX_AD_UUID_BYTES 32
  3808. static void cmd_add_adv(int argc, char **argv)
  3809. {
  3810. struct mgmt_cp_add_advertising *cp = NULL;
  3811. int opt;
  3812. uint8_t *adv_data = NULL, *scan_rsp = NULL;
  3813. size_t adv_len = 0, scan_rsp_len = 0;
  3814. size_t cp_len;
  3815. uint8_t uuids[MAX_AD_UUID_BYTES];
  3816. size_t uuid_bytes = 0;
  3817. uint8_t uuid_type = 0;
  3818. uint16_t timeout = 0, duration = 0;
  3819. uint8_t instance;
  3820. uuid_t uuid;
  3821. bool success = false;
  3822. bool quit = true;
  3823. uint32_t flags = 0;
  3824. uint16_t index;
  3825. while ((opt = getopt_long(argc, argv, "+u:d:s:t:D:P:cglmphna",
  3826. add_adv_options, NULL)) != -1) {
  3827. switch (opt) {
  3828. case 'u':
  3829. if (bt_string2uuid(&uuid, optarg) < 0) {
  3830. print("Invalid UUID: %s", optarg);
  3831. goto done;
  3832. }
  3833. if (uuid_type && uuid_type != uuid.type) {
  3834. print("UUID types must be consistent");
  3835. goto done;
  3836. }
  3837. if (uuid.type == SDP_UUID16) {
  3838. if (uuid_bytes + 2 >= MAX_AD_UUID_BYTES) {
  3839. print("Too many UUIDs");
  3840. goto done;
  3841. }
  3842. put_le16(uuid.value.uuid16, uuids + uuid_bytes);
  3843. uuid_bytes += 2;
  3844. } else if (uuid.type == SDP_UUID128) {
  3845. if (uuid_bytes + 16 >= MAX_AD_UUID_BYTES) {
  3846. print("Too many UUIDs");
  3847. goto done;
  3848. }
  3849. bswap_128(uuid.value.uuid128.data,
  3850. uuids + uuid_bytes);
  3851. uuid_bytes += 16;
  3852. } else {
  3853. printf("Unsupported UUID type");
  3854. goto done;
  3855. }
  3856. if (!uuid_type)
  3857. uuid_type = uuid.type;
  3858. break;
  3859. case 'd':
  3860. if (adv_len) {
  3861. print("Only one adv-data option allowed");
  3862. goto done;
  3863. }
  3864. if (!parse_bytes(optarg, &adv_data, &adv_len))
  3865. goto done;
  3866. break;
  3867. case 's':
  3868. if (scan_rsp_len) {
  3869. print("Only one scan-rsp option allowed");
  3870. goto done;
  3871. }
  3872. if (!parse_bytes(optarg, &scan_rsp, &scan_rsp_len))
  3873. goto done;
  3874. break;
  3875. case 't':
  3876. timeout = strtol(optarg, NULL, 0);
  3877. break;
  3878. case 'D':
  3879. duration = strtol(optarg, NULL, 0);
  3880. break;
  3881. case 'c':
  3882. flags |= MGMT_ADV_FLAG_CONNECTABLE;
  3883. break;
  3884. case 'g':
  3885. flags |= MGMT_ADV_FLAG_DISCOV;
  3886. break;
  3887. case 'l':
  3888. flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
  3889. break;
  3890. case 'm':
  3891. flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
  3892. break;
  3893. case 'p':
  3894. flags |= MGMT_ADV_FLAG_TX_POWER;
  3895. break;
  3896. case 'n':
  3897. flags |= MGMT_ADV_FLAG_LOCAL_NAME;
  3898. break;
  3899. case 'a':
  3900. flags |= MGMT_ADV_FLAG_APPEARANCE;
  3901. break;
  3902. case 'P':
  3903. if (strcasecmp(optarg, "1M") == 0)
  3904. flags |= MGMT_ADV_FLAG_SEC_1M;
  3905. else if (strcasecmp(optarg, "2M") == 0)
  3906. flags |= MGMT_ADV_FLAG_SEC_2M;
  3907. else if (strcasecmp(optarg, "CODED") == 0)
  3908. flags |= MGMT_ADV_FLAG_SEC_CODED;
  3909. else
  3910. goto done;
  3911. break;
  3912. case 'h':
  3913. success = true;
  3914. /* fall through */
  3915. default:
  3916. add_adv_usage();
  3917. optind = 0;
  3918. goto done;
  3919. }
  3920. }
  3921. argc -= optind;
  3922. argv += optind;
  3923. optind = 0;
  3924. if (argc != 1) {
  3925. add_adv_usage();
  3926. goto done;
  3927. }
  3928. if (uuid_bytes)
  3929. uuid_bytes += 2;
  3930. instance = strtol(argv[0], NULL, 0);
  3931. index = mgmt_index;
  3932. if (index == MGMT_INDEX_NONE)
  3933. index = 0;
  3934. cp_len = sizeof(*cp) + uuid_bytes + adv_len + scan_rsp_len;
  3935. cp = malloc0(cp_len);
  3936. if (!cp)
  3937. goto done;
  3938. cp->instance = instance;
  3939. put_le32(flags, &cp->flags);
  3940. put_le16(timeout, &cp->timeout);
  3941. put_le16(duration, &cp->duration);
  3942. cp->adv_data_len = adv_len + uuid_bytes;
  3943. cp->scan_rsp_len = scan_rsp_len;
  3944. if (uuid_bytes) {
  3945. cp->data[0] = uuid_bytes - 1;
  3946. cp->data[1] = uuid_type == SDP_UUID16 ? 0x03 : 0x07;
  3947. memcpy(cp->data + 2, uuids, uuid_bytes - 2);
  3948. }
  3949. memcpy(cp->data + uuid_bytes, adv_data, adv_len);
  3950. memcpy(cp->data + uuid_bytes + adv_len, scan_rsp, scan_rsp_len);
  3951. if (!mgmt_send(mgmt, MGMT_OP_ADD_ADVERTISING, index, cp_len, cp,
  3952. add_adv_rsp, NULL, NULL)) {
  3953. error("Unable to send \"Add Advertising\" command");
  3954. goto done;
  3955. }
  3956. quit = false;
  3957. done:
  3958. free(adv_data);
  3959. free(scan_rsp);
  3960. free(cp);
  3961. if (quit)
  3962. bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
  3963. }
  3964. static void rm_adv_rsp(uint8_t status, uint16_t len, const void *param,
  3965. void *user_data)
  3966. {
  3967. const struct mgmt_rp_remove_advertising *rp = param;
  3968. if (status != 0) {
  3969. error("Remove Advertising failed with status 0x%02x (%s)",
  3970. status, mgmt_errstr(status));
  3971. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3972. }
  3973. if (len != sizeof(*rp)) {
  3974. error("Invalid Remove Advertising response length (%u)", len);
  3975. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3976. }
  3977. print("Instance removed: %u", rp->instance);
  3978. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  3979. }
  3980. static void cmd_rm_adv(int argc, char **argv)
  3981. {
  3982. struct mgmt_cp_remove_advertising cp;
  3983. uint8_t instance;
  3984. uint16_t index;
  3985. instance = strtol(argv[1], NULL, 0);
  3986. index = mgmt_index;
  3987. if (index == MGMT_INDEX_NONE)
  3988. index = 0;
  3989. memset(&cp, 0, sizeof(cp));
  3990. cp.instance = instance;
  3991. if (!mgmt_send(mgmt, MGMT_OP_REMOVE_ADVERTISING, index, sizeof(cp), &cp,
  3992. rm_adv_rsp, NULL, NULL)) {
  3993. error("Unable to send \"Remove Advertising\" command");
  3994. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  3995. }
  3996. }
  3997. static void cmd_clr_adv(int argc, char **argv)
  3998. {
  3999. char *all_instances = "0";
  4000. char *rm_argv[] = { "rm-adv", all_instances, NULL };
  4001. cmd_rm_adv(2, rm_argv);
  4002. }
  4003. static void appearance_rsp(uint8_t status, uint16_t len, const void *param,
  4004. void *user_data)
  4005. {
  4006. if (status != 0)
  4007. error("Could not set Appearance with status 0x%02x (%s)",
  4008. status, mgmt_errstr(status));
  4009. else
  4010. print("Appearance successfully set");
  4011. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  4012. }
  4013. static void cmd_appearance(int argc, char **argv)
  4014. {
  4015. struct mgmt_cp_set_appearance cp;
  4016. uint16_t index;
  4017. index = mgmt_index;
  4018. if (index == MGMT_INDEX_NONE)
  4019. index = 0;
  4020. cp.appearance = cpu_to_le16(strtol(argv[1], NULL, 0));
  4021. if (mgmt_send(mgmt, MGMT_OP_SET_APPEARANCE, index, sizeof(cp), &cp,
  4022. appearance_rsp, NULL, NULL) == 0) {
  4023. error("Unable to send appearance cmd");
  4024. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4025. }
  4026. }
  4027. static const char *phys_str[] = {
  4028. "BR1M1SLOT",
  4029. "BR1M3SLOT",
  4030. "BR1M5SLOT",
  4031. "EDR2M1SLOT",
  4032. "EDR2M3SLOT",
  4033. "EDR2M5SLOT",
  4034. "EDR3M1SLOT",
  4035. "EDR3M3SLOT",
  4036. "EDR3M5SLOT",
  4037. "LE1MTX",
  4038. "LE1MRX",
  4039. "LE2MTX",
  4040. "LE2MRX",
  4041. "LECODEDTX",
  4042. "LECODEDRX",
  4043. };
  4044. static const char *phys2str(uint32_t phys)
  4045. {
  4046. static char str[256];
  4047. unsigned int i;
  4048. int off;
  4049. off = 0;
  4050. str[0] = '\0';
  4051. for (i = 0; i < NELEM(phys_str); i++) {
  4052. if ((phys & (1 << i)) != 0)
  4053. off += snprintf(str + off, sizeof(str) - off, "%s ",
  4054. phys_str[i]);
  4055. }
  4056. return str;
  4057. }
  4058. static bool str2phy(const char *phy_str, uint32_t *phy_val)
  4059. {
  4060. unsigned int i;
  4061. for (i = 0; i < NELEM(phys_str); i++) {
  4062. if (strcasecmp(phys_str[i], phy_str) == 0) {
  4063. *phy_val = (1 << i);
  4064. return true;
  4065. }
  4066. }
  4067. return false;
  4068. }
  4069. static void get_phy_rsp(uint8_t status, uint16_t len, const void *param,
  4070. void *user_data)
  4071. {
  4072. const struct mgmt_rp_get_phy_confguration *rp = param;
  4073. uint32_t supported_phys, selected_phys, configurable_phys;
  4074. if (status != 0) {
  4075. error("Get PHY Configuration failed with status 0x%02x (%s)",
  4076. status, mgmt_errstr(status));
  4077. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4078. }
  4079. if (len < sizeof(*rp)) {
  4080. error("Too small get-phy reply (%u bytes)", len);
  4081. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4082. }
  4083. supported_phys = get_le32(&rp->supported_phys);
  4084. configurable_phys = get_le32(&rp->configurable_phys);
  4085. selected_phys = get_le32(&rp->selected_phys);
  4086. print("Supported phys: %s", phys2str(supported_phys));
  4087. print("Configurable phys: %s", phys2str(configurable_phys));
  4088. print("Selected phys: %s", phys2str(selected_phys));
  4089. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  4090. }
  4091. static void get_phy(void)
  4092. {
  4093. uint16_t index;
  4094. index = mgmt_index;
  4095. if (index == MGMT_INDEX_NONE)
  4096. index = 0;
  4097. if (mgmt_send(mgmt, MGMT_OP_GET_PHY_CONFIGURATION, index, 0, NULL,
  4098. get_phy_rsp, NULL, NULL) == 0) {
  4099. error("Unable to send Get PHY cmd");
  4100. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4101. }
  4102. }
  4103. static void set_phy_rsp(uint8_t status, uint16_t len, const void *param,
  4104. void *user_data)
  4105. {
  4106. if (status != 0) {
  4107. error("Could not set PHY Configuration with status 0x%02x (%s)",
  4108. status, mgmt_errstr(status));
  4109. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4110. }
  4111. print("PHY Configuration successfully set");
  4112. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  4113. }
  4114. static void cmd_phy(int argc, char **argv)
  4115. {
  4116. struct mgmt_cp_set_phy_confguration cp;
  4117. int i;
  4118. uint32_t phys = 0;
  4119. uint16_t index;
  4120. if (argc < 2)
  4121. return get_phy();
  4122. for (i = 1; i < argc; i++) {
  4123. uint32_t phy_val;
  4124. if (str2phy(argv[i], &phy_val))
  4125. phys |= phy_val;
  4126. }
  4127. cp.selected_phys = cpu_to_le32(phys);
  4128. index = mgmt_index;
  4129. if (index == MGMT_INDEX_NONE)
  4130. index = 0;
  4131. if (mgmt_send(mgmt, MGMT_OP_SET_PHY_CONFIGURATION, index, sizeof(cp),
  4132. &cp, set_phy_rsp, NULL, NULL) == 0) {
  4133. error("Unable to send %s cmd",
  4134. mgmt_opstr(MGMT_OP_SET_PHY_CONFIGURATION));
  4135. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4136. }
  4137. }
  4138. static void cmd_wbs(int argc, char **argv)
  4139. {
  4140. cmd_setting(MGMT_OP_SET_WIDEBAND_SPEECH, argc, argv);
  4141. }
  4142. static const char * const advmon_features_str[] = {
  4143. "Pattern monitor with logic OR.",
  4144. };
  4145. static const char *advmon_features2str(uint32_t features)
  4146. {
  4147. static char str[512];
  4148. unsigned int off, i;
  4149. off = 0;
  4150. snprintf(str, sizeof(str), "\n\tNone");
  4151. for (i = 0; i < NELEM(advmon_features_str); i++) {
  4152. if ((features & (1 << i)) != 0 && off < sizeof(str))
  4153. off += snprintf(str + off, sizeof(str) - off, "\n\t%s",
  4154. advmon_features_str[i]);
  4155. }
  4156. return str;
  4157. }
  4158. static void advmon_features_rsp(uint8_t status, uint16_t len, const void *param,
  4159. void *user_data)
  4160. {
  4161. const struct mgmt_rp_read_adv_monitor_features *rp = param;
  4162. uint32_t supported_features, enabled_features;
  4163. uint16_t num_handles;
  4164. int i;
  4165. if (status != MGMT_STATUS_SUCCESS) {
  4166. error("Reading adv monitor features failed with status 0x%02x "
  4167. "(%s)", status, mgmt_errstr(status));
  4168. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4169. }
  4170. if (len < sizeof(*rp)) {
  4171. error("Too small adv monitor features reply (%u bytes)", len);
  4172. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4173. }
  4174. supported_features = le32_to_cpu(rp->supported_features);
  4175. enabled_features = le32_to_cpu(rp->enabled_features);
  4176. num_handles = le16_to_cpu(rp->num_handles);
  4177. if (len < sizeof(*rp) + num_handles * sizeof(uint16_t)) {
  4178. error("Handles count (%u) doesn't match reply length (%u)",
  4179. num_handles, len);
  4180. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4181. }
  4182. print("Supported features:%s", advmon_features2str(supported_features));
  4183. print("Enabled features:%s", advmon_features2str(enabled_features));
  4184. print("Max number of handles: %u", le16_to_cpu(rp->max_num_handles));
  4185. print("Max number of patterns: %u", rp->max_num_patterns);
  4186. print("Handles list with %u item%s", num_handles,
  4187. num_handles == 0 ? "" : num_handles == 1 ? ":" : "s:");
  4188. for (i = 0; i < num_handles; i++)
  4189. print("\t0x%04x ", le16_to_cpu(rp->handles[i]));
  4190. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  4191. }
  4192. static void cmd_advmon_features(int argc, char **argv)
  4193. {
  4194. uint16_t index;
  4195. index = mgmt_index;
  4196. if (index == MGMT_INDEX_NONE)
  4197. index = 0;
  4198. if (!mgmt_send(mgmt, MGMT_OP_READ_ADV_MONITOR_FEATURES, index, 0, NULL,
  4199. advmon_features_rsp, NULL, NULL)) {
  4200. error("Unable to send advertising monitor features command");
  4201. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4202. }
  4203. }
  4204. static void advmon_add_rsp(uint8_t status, uint16_t len, const void *param,
  4205. void *user_data)
  4206. {
  4207. const struct mgmt_rp_add_adv_patterns_monitor *rp = param;
  4208. if (status != MGMT_STATUS_SUCCESS) {
  4209. error("Could not add advertisement monitor with status "
  4210. "0x%02x (%s)", status, mgmt_errstr(status));
  4211. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4212. }
  4213. print("Advertisement monitor with handle:0x%04x added",
  4214. le16_to_cpu(rp->monitor_handle));
  4215. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  4216. }
  4217. static bool str2pattern(struct mgmt_adv_pattern *pattern, const char *str)
  4218. {
  4219. int type_len, offset_len, offset_end_pos, str_len;
  4220. int i, j;
  4221. char pattern_str[62] = { 0 };
  4222. char tmp;
  4223. if (sscanf(str, "%2hhx%n:%2hhx%n:%s", &pattern->ad_type, &type_len,
  4224. &pattern->offset, &offset_end_pos, pattern_str) != 3)
  4225. return false;
  4226. offset_len = offset_end_pos - type_len - 1;
  4227. str_len = strlen(pattern_str);
  4228. pattern->length = str_len / 2 + str_len % 2;
  4229. if (type_len > 2 || offset_len > 2 ||
  4230. pattern->offset + pattern->length > 31)
  4231. return false;
  4232. for (i = 0, j = 0; i < str_len; i++, j++) {
  4233. if (sscanf(&pattern_str[i++], "%2hhx", &pattern->value[j])
  4234. != 1)
  4235. return false;
  4236. if (i < str_len && sscanf(&pattern_str[i], "%1hhx", &tmp) != 1)
  4237. return false;
  4238. }
  4239. return true;
  4240. }
  4241. static struct option add_monitor_rssi_options[] = {
  4242. { "help", 0, 0, 'h' },
  4243. { "high-threshold", 1, 0, 'R' },
  4244. { "low-threshold", 1, 0, 'r' },
  4245. { "high-timeout", 1, 0, 'T' },
  4246. { "low-timeout", 1, 0, 't' },
  4247. { "sampling", 1, 0, 's' },
  4248. { 0, 0, 0, 0 }
  4249. };
  4250. static void advmon_add_pattern_usage(void)
  4251. {
  4252. bt_shell_usage();
  4253. print("patterns format:\n"
  4254. "\t<ad_type:offset:pattern> [patterns]\n"
  4255. "e.g.:\n"
  4256. "\tadd-pattern 0:1:c504 ff:a:9a55beef");
  4257. }
  4258. static void advmon_add_pattern_rssi_usage(void)
  4259. {
  4260. bt_shell_usage();
  4261. print("RSSI options:\n"
  4262. "\t -R, --high-threshold <dBm> "
  4263. "RSSI high threshold. Default: -70\n"
  4264. "\t -r, --low-threshold <dBm> "
  4265. "RSSI low threshold. Default: -50\n"
  4266. "\t -T, --high-timeout <s> "
  4267. "RSSI high threshold duration. Default: 0\n"
  4268. "\t -t, --low-timeout <s> "
  4269. "RSSI low threshold duration. Default: 5\n"
  4270. "\t -s, --sampling <N * 100ms> "
  4271. "RSSI sampling period. Default: 0\n"
  4272. "patterns format:\n"
  4273. "\t<ad_type:offset:pattern> [patterns]\n"
  4274. "e.g.:\n"
  4275. "\tadd-pattern-rssi -R 0xb2 -r -102 0:1:c504 ff:a:9a55beef");
  4276. }
  4277. static void cmd_advmon_add_pattern(int argc, char **argv)
  4278. {
  4279. bool success = true;
  4280. uint16_t index;
  4281. int i, cp_len;
  4282. struct mgmt_cp_add_adv_monitor *cp = NULL;
  4283. if (!strcmp(argv[1], "-h"))
  4284. goto done;
  4285. argc -= 1;
  4286. argv += 1;
  4287. cp_len = sizeof(*cp) + argc * sizeof(struct mgmt_adv_pattern);
  4288. cp = malloc0(cp_len);
  4289. if (!cp) {
  4290. error("Failed to alloc patterns.");
  4291. success = false;
  4292. goto done;
  4293. }
  4294. cp->pattern_count = argc;
  4295. for (i = 0; i < argc; i++) {
  4296. if (!str2pattern(&cp->patterns[i], argv[i])) {
  4297. error("Failed to parse monitor patterns.");
  4298. success = false;
  4299. goto done;
  4300. }
  4301. }
  4302. index = mgmt_index;
  4303. if (index == MGMT_INDEX_NONE)
  4304. index = 0;
  4305. if (!mgmt_send(mgmt, MGMT_OP_ADD_ADV_PATTERNS_MONITOR, index,
  4306. cp_len, cp, advmon_add_rsp, NULL, NULL)) {
  4307. error("Unable to send Add Advertising Monitor command");
  4308. success = false;
  4309. goto done;
  4310. }
  4311. free(cp);
  4312. return;
  4313. done:
  4314. free(cp);
  4315. advmon_add_pattern_usage();
  4316. bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
  4317. }
  4318. static void cmd_advmon_add_pattern_rssi(int argc, char **argv)
  4319. {
  4320. bool success = true;
  4321. int opt;
  4322. int8_t rssi_low = -70;
  4323. int8_t rssi_high = -50;
  4324. uint16_t rssi_low_timeout = 5;
  4325. uint16_t rssi_high_timeout = 0;
  4326. uint8_t rssi_sampling_period = 0;
  4327. uint16_t index;
  4328. int i, cp_len;
  4329. struct mgmt_cp_add_adv_patterns_monitor_rssi *cp = NULL;
  4330. while ((opt = getopt_long(argc, argv, "+hr:R:t:T:s:",
  4331. add_monitor_rssi_options, NULL)) != -1) {
  4332. switch (opt) {
  4333. case 'h':
  4334. goto done;
  4335. case 'r':
  4336. rssi_low = strtol(optarg, NULL, 0);
  4337. break;
  4338. case 'R':
  4339. rssi_high = strtol(optarg, NULL, 0);
  4340. break;
  4341. case 't':
  4342. rssi_low_timeout = strtol(optarg, NULL, 0);
  4343. break;
  4344. case 'T':
  4345. rssi_high_timeout = strtol(optarg, NULL, 0);
  4346. break;
  4347. case 's':
  4348. rssi_sampling_period = strtol(optarg, NULL, 0);
  4349. break;
  4350. default:
  4351. success = false;
  4352. goto done;
  4353. }
  4354. }
  4355. argc -= optind;
  4356. argv += optind;
  4357. optind = 0;
  4358. cp_len = sizeof(*cp) + argc * sizeof(struct mgmt_adv_pattern);
  4359. cp = malloc0(cp_len);
  4360. if (!cp) {
  4361. error("Failed to alloc patterns.");
  4362. success = false;
  4363. goto done;
  4364. }
  4365. cp->pattern_count = argc;
  4366. cp->rssi.high_threshold = rssi_high;
  4367. cp->rssi.low_threshold = rssi_low;
  4368. cp->rssi.high_threshold_timeout = htobs(rssi_high_timeout);
  4369. cp->rssi.low_threshold_timeout = htobs(rssi_low_timeout);
  4370. cp->rssi.sampling_period = rssi_sampling_period;
  4371. for (i = 0; i < argc; i++) {
  4372. if (!str2pattern(&cp->patterns[i], argv[i])) {
  4373. error("Failed to parse monitor patterns.");
  4374. success = false;
  4375. goto done;
  4376. }
  4377. }
  4378. index = mgmt_index;
  4379. if (index == MGMT_INDEX_NONE)
  4380. index = 0;
  4381. if (!mgmt_send(mgmt, MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, index,
  4382. cp_len, cp, advmon_add_rsp, NULL, NULL)) {
  4383. error("Unable to send Add Advertising Monitor RSSI command");
  4384. success = false;
  4385. goto done;
  4386. }
  4387. free(cp);
  4388. return;
  4389. done:
  4390. free(cp);
  4391. optind = 0;
  4392. advmon_add_pattern_rssi_usage();
  4393. bt_shell_noninteractive_quit(success ? EXIT_SUCCESS : EXIT_FAILURE);
  4394. }
  4395. static void advmon_remove_rsp(uint8_t status, uint16_t len, const void *param,
  4396. void *user_data)
  4397. {
  4398. const struct mgmt_rp_remove_adv_monitor *rp = param;
  4399. if (status != MGMT_STATUS_SUCCESS) {
  4400. error("Could not remove advertisement monitor with status "
  4401. "0x%02x (%s)", status, mgmt_errstr(status));
  4402. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4403. }
  4404. print("Advertisement monitor with handle: 0x%04x removed",
  4405. le16_to_cpu(rp->monitor_handle));
  4406. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  4407. }
  4408. static void cmd_advmon_remove(int argc, char **argv)
  4409. {
  4410. struct mgmt_cp_remove_adv_monitor cp;
  4411. uint16_t index, monitor_handle;
  4412. index = mgmt_index;
  4413. if (index == MGMT_INDEX_NONE)
  4414. index = 0;
  4415. if (sscanf(argv[1], "%hx", &monitor_handle) != 1) {
  4416. error("Wrong formatted handle argument");
  4417. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4418. }
  4419. cp.monitor_handle = cpu_to_le16(monitor_handle);
  4420. if (mgmt_send(mgmt, MGMT_OP_REMOVE_ADV_MONITOR, index, sizeof(cp), &cp,
  4421. advmon_remove_rsp, NULL, NULL) == 0) {
  4422. error("Unable to send appearance cmd");
  4423. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  4424. }
  4425. }
  4426. static void register_mgmt_callbacks(struct mgmt *mgmt, uint16_t index)
  4427. {
  4428. mgmt_register(mgmt, MGMT_EV_CONTROLLER_ERROR, index, controller_error,
  4429. NULL, NULL);
  4430. mgmt_register(mgmt, MGMT_EV_INDEX_ADDED, index, index_added,
  4431. NULL, NULL);
  4432. mgmt_register(mgmt, MGMT_EV_INDEX_REMOVED, index, index_removed,
  4433. NULL, NULL);
  4434. mgmt_register(mgmt, MGMT_EV_NEW_SETTINGS, index, new_settings,
  4435. NULL, NULL);
  4436. mgmt_register(mgmt, MGMT_EV_DISCOVERING, index, discovering,
  4437. NULL, NULL);
  4438. mgmt_register(mgmt, MGMT_EV_NEW_LINK_KEY, index, new_link_key,
  4439. NULL, NULL);
  4440. mgmt_register(mgmt, MGMT_EV_DEVICE_CONNECTED, index, connected,
  4441. NULL, NULL);
  4442. mgmt_register(mgmt, MGMT_EV_DEVICE_DISCONNECTED, index, disconnected,
  4443. NULL, NULL);
  4444. mgmt_register(mgmt, MGMT_EV_CONNECT_FAILED, index, conn_failed,
  4445. NULL, NULL);
  4446. mgmt_register(mgmt, MGMT_EV_AUTH_FAILED, index, auth_failed,
  4447. NULL, NULL);
  4448. mgmt_register(mgmt, MGMT_EV_CLASS_OF_DEV_CHANGED, index,
  4449. class_of_dev_changed, NULL, NULL);
  4450. mgmt_register(mgmt, MGMT_EV_LOCAL_NAME_CHANGED, index,
  4451. local_name_changed, NULL, NULL);
  4452. mgmt_register(mgmt, MGMT_EV_DEVICE_FOUND, index, device_found,
  4453. mgmt, NULL);
  4454. mgmt_register(mgmt, MGMT_EV_PIN_CODE_REQUEST, index, request_pin,
  4455. mgmt, NULL);
  4456. mgmt_register(mgmt, MGMT_EV_USER_CONFIRM_REQUEST, index, user_confirm,
  4457. mgmt, NULL);
  4458. mgmt_register(mgmt, MGMT_EV_USER_PASSKEY_REQUEST, index,
  4459. request_passkey, mgmt, NULL);
  4460. mgmt_register(mgmt, MGMT_EV_PASSKEY_NOTIFY, index,
  4461. passkey_notify, mgmt, NULL);
  4462. mgmt_register(mgmt, MGMT_EV_UNCONF_INDEX_ADDED, index,
  4463. unconf_index_added, NULL, NULL);
  4464. mgmt_register(mgmt, MGMT_EV_UNCONF_INDEX_REMOVED, index,
  4465. unconf_index_removed, NULL, NULL);
  4466. mgmt_register(mgmt, MGMT_EV_NEW_CONFIG_OPTIONS, index,
  4467. new_config_options, NULL, NULL);
  4468. mgmt_register(mgmt, MGMT_EV_EXT_INDEX_ADDED, index,
  4469. ext_index_added, NULL, NULL);
  4470. mgmt_register(mgmt, MGMT_EV_EXT_INDEX_REMOVED, index,
  4471. ext_index_removed, NULL, NULL);
  4472. mgmt_register(mgmt, MGMT_EV_LOCAL_OOB_DATA_UPDATED, index,
  4473. local_oob_data_updated, NULL, NULL);
  4474. mgmt_register(mgmt, MGMT_EV_ADVERTISING_ADDED, index,
  4475. advertising_added, NULL, NULL);
  4476. mgmt_register(mgmt, MGMT_EV_ADVERTISING_REMOVED, index,
  4477. advertising_removed, NULL, NULL);
  4478. mgmt_register(mgmt, MGMT_EV_DEVICE_FLAGS_CHANGED, index,
  4479. flags_changed, NULL, NULL);
  4480. mgmt_register(mgmt, MGMT_EV_ADV_MONITOR_ADDED, index, advmon_added,
  4481. NULL, NULL);
  4482. mgmt_register(mgmt, MGMT_EV_ADV_MONITOR_REMOVED, index, advmon_removed,
  4483. NULL, NULL);
  4484. }
  4485. static void cmd_select(int argc, char **argv)
  4486. {
  4487. mgmt_cancel_all(mgmt);
  4488. mgmt_unregister_all(mgmt);
  4489. set_index(argv[1]);
  4490. register_mgmt_callbacks(mgmt, mgmt_index);
  4491. print("Selected index %u", mgmt_index);
  4492. update_prompt(mgmt_index);
  4493. }
  4494. static const struct bt_shell_menu monitor_menu = {
  4495. .name = "monitor",
  4496. .desc = "Advertisement Monitor Submenu",
  4497. .entries = {
  4498. { "features", NULL,
  4499. cmd_advmon_features, "Show advertisement monitor "
  4500. "features" },
  4501. { "remove", "<handle>",
  4502. cmd_advmon_remove, "Remove advertisement monitor " },
  4503. { "add-pattern", "[-h] <patterns>",
  4504. cmd_advmon_add_pattern, "Add advertisement monitor pattern" },
  4505. { "add-pattern-rssi", "[options] <patterns>",
  4506. cmd_advmon_add_pattern_rssi,
  4507. "Add advertisement monitor pattern with RSSI options" },
  4508. { } },
  4509. };
  4510. static const struct bt_shell_menu main_menu = {
  4511. .name = "main",
  4512. .entries = {
  4513. { "select", "<index>",
  4514. cmd_select, "Select a different index" },
  4515. { "revision", NULL,
  4516. cmd_revision, "Get the MGMT Revision" },
  4517. { "commands", NULL,
  4518. cmd_commands, "List supported commands" },
  4519. { "config", NULL,
  4520. cmd_config, "Show configuration info" },
  4521. { "info", NULL,
  4522. cmd_info, "Show controller info" },
  4523. { "extinfo", NULL,
  4524. cmd_extinfo, "Show extended controller info" },
  4525. { "auto-power", NULL,
  4526. cmd_auto_power, "Power all available features" },
  4527. { "power", "<on/off>",
  4528. cmd_power, "Toggle powered state" },
  4529. { "discov", "<yes/no/limited> [timeout]",
  4530. cmd_discov, "Toggle discoverable state" },
  4531. { "connectable", "<on/off>",
  4532. cmd_connectable, "Toggle connectable state" },
  4533. { "fast-conn", "<on/off>",
  4534. cmd_fast_conn, "Toggle fast connectable state" },
  4535. { "bondable", "<on/off>",
  4536. cmd_bondable, "Toggle bondable state" },
  4537. { "pairable", "<on/off>",
  4538. cmd_bondable, "Toggle bondable state" },
  4539. { "linksec", "<on/off>",
  4540. cmd_linksec, "Toggle link level security" },
  4541. { "ssp", "<on/off>",
  4542. cmd_ssp, "Toggle SSP mode" },
  4543. { "sc", "<on/off/only>",
  4544. cmd_sc, "Toogle SC support" },
  4545. { "hs", "<on/off>",
  4546. cmd_hs, "Toggle HS support" },
  4547. { "le", "<on/off>",
  4548. cmd_le, "Toggle LE support" },
  4549. { "advertising", "<on/off>",
  4550. cmd_advertising, "Toggle LE advertising", },
  4551. { "bredr", "<on/off>",
  4552. cmd_bredr, "Toggle BR/EDR support", },
  4553. { "privacy", "<on/off> [irk]",
  4554. cmd_privacy, "Toggle privacy support" },
  4555. { "class", "<major> <minor>",
  4556. cmd_class, "Set device major/minor class" },
  4557. { "disconnect", "[-t type] <remote address>",
  4558. cmd_disconnect, "Disconnect device" },
  4559. { "con", NULL,
  4560. cmd_con, "List connections" },
  4561. { "find", "[-l|-b] [-L]",
  4562. cmd_find, "Discover nearby devices" },
  4563. { "find-service", "[-u UUID] [-r RSSI_Threshold] [-l|-b]",
  4564. cmd_find_service, "Discover nearby service" },
  4565. { "stop-find", "[-l|-b]",
  4566. cmd_stop_find, "Stop discovery" },
  4567. { "name", "<name> [shortname]",
  4568. cmd_name, "Set local name" },
  4569. { "pair", "[-c cap] [-t type] <remote address>",
  4570. cmd_pair, "Pair with a remote device" },
  4571. { "cancelpair", "[-t type] <remote address>",
  4572. cmd_cancel_pair, "Cancel pairing" },
  4573. { "unpair", "[-t type] <remote address>",
  4574. cmd_unpair, "Unpair device" },
  4575. { "keys", NULL,
  4576. cmd_keys, "Load Link Keys" },
  4577. { "ltks", NULL,
  4578. cmd_ltks, "Load Long Term Keys" },
  4579. { "irks", "[--local index] [--file file path]",
  4580. cmd_irks, "Load Identity Resolving Keys" },
  4581. { "block", "[-t type] <remote address>",
  4582. cmd_block, "Block Device" },
  4583. { "unblock", "[-t type] <remote address>",
  4584. cmd_unblock, "Unblock Device" },
  4585. { "add-uuid", "<UUID> <service class hint>",
  4586. cmd_add_uuid, "Add UUID" },
  4587. { "rm-uuid", "<UUID>",
  4588. cmd_remove_uuid, "Remove UUID" },
  4589. { "clr-uuids", NULL,
  4590. cmd_clr_uuids, "Clear UUIDs" },
  4591. { "local-oob", NULL,
  4592. cmd_local_oob, "Local OOB data" },
  4593. { "remote-oob", "[-t <addr_type>] [-r <rand192>] "
  4594. "[-h <hash192>] [-R <rand256>] "
  4595. "[-H <hash256>] <addr>",
  4596. cmd_remote_oob, "Remote OOB data" },
  4597. { "did", "<source>:<vendor>:<product>:<version>",
  4598. cmd_did, "Set Device ID" },
  4599. { "static-addr", "<address>",
  4600. cmd_static_addr, "Set static address" },
  4601. { "public-addr", "<address>",
  4602. cmd_public_addr, "Set public address" },
  4603. { "ext-config", "<on/off>",
  4604. cmd_ext_config, "External configuration" },
  4605. { "debug-keys", "<on/off>",
  4606. cmd_debug_keys, "Toogle debug keys" },
  4607. { "conn-info", "[-t type] <remote address>",
  4608. cmd_conn_info, "Get connection information" },
  4609. { "io-cap", "<cap>",
  4610. cmd_io_cap, "Set IO Capability" },
  4611. { "scan-params", "<interval> <window>",
  4612. cmd_scan_params, "Set Scan Parameters" },
  4613. { "get-clock", "[address]",
  4614. cmd_clock_info, "Get Clock Information" },
  4615. { "add-device", "[-a action] [-t type] <address>",
  4616. cmd_add_device, "Add Device" },
  4617. { "del-device", "[-t type] <address>",
  4618. cmd_del_device, "Remove Device" },
  4619. { "clr-devices", NULL,
  4620. cmd_clr_devices, "Clear Devices" },
  4621. { "bredr-oob", NULL,
  4622. cmd_bredr_oob, "Local OOB data (BR/EDR)" },
  4623. { "le-oob", NULL,
  4624. cmd_le_oob, "Local OOB data (LE)" },
  4625. { "advinfo", NULL,
  4626. cmd_advinfo, "Show advertising features" },
  4627. { "advsize", "[options] <instance_id>",
  4628. cmd_advsize, "Show advertising size info" },
  4629. { "add-adv", "[options] <instance_id>",
  4630. cmd_add_adv, "Add advertising instance" },
  4631. { "rm-adv", "<instance_id>",
  4632. cmd_rm_adv, "Remove advertising instance" },
  4633. { "clr-adv", NULL,
  4634. cmd_clr_adv, "Clear advertising instances" },
  4635. { "appearance", "<appearance>",
  4636. cmd_appearance, "Set appearance" },
  4637. { "phy", "[LE1MTX] [LE1MRX] [LE2MTX] [LE2MRX] "
  4638. "[LECODEDTX] [LECODEDRX] "
  4639. "[BR1M1SLOT] [BR1M3SLOT] [BR1M5SLOT]"
  4640. "[EDR2M1SLOT] [EDR2M3SLOT] [EDR2M5SLOT]"
  4641. "[EDR3M1SLOT] [EDR3M3SLOT] [EDR3M5SLOT]",
  4642. cmd_phy, "Get/Set PHY Configuration" },
  4643. { "wbs", "<on/off>",
  4644. cmd_wbs, "Toggle Wideband-Speech support"},
  4645. { "secinfo", NULL,
  4646. cmd_secinfo, "Show security information" },
  4647. { "expinfo", NULL,
  4648. cmd_expinfo, "Show experimental features" },
  4649. { "exp-debug", "<on/off>",
  4650. cmd_exp_debug, "Set debug feature" },
  4651. { "exp-privacy", "<on/off>",
  4652. cmd_exp_privacy, "Set LL privacy feature" },
  4653. { "exp-quality", "<on/off>", cmd_exp_quality,
  4654. "Set bluetooth quality report feature" },
  4655. { "exp-offload", "<on/off>",
  4656. cmd_exp_offload_codecs, "Toggle codec support" },
  4657. { "read-sysconfig", NULL,
  4658. cmd_read_sysconfig, "Read System Configuration" },
  4659. { "set-sysconfig", "<-v|-h> [options...]",
  4660. cmd_set_sysconfig, "Set System Configuration" },
  4661. { "get-flags", "[-t type] <address>",
  4662. cmd_get_flags, "Get device flags" },
  4663. { "set-flags", "[-f flags] [-t type] <address>",
  4664. cmd_set_flags, "Set device flags" },
  4665. {} },
  4666. };
  4667. static void mgmt_debug(const char *str, void *user_data)
  4668. {
  4669. const char *prefix = user_data;
  4670. print("%s%s", prefix, str);
  4671. }
  4672. static const char *index_option;
  4673. static struct option main_options[] = {
  4674. { "index", 1, 0, 'i' },
  4675. { 0, 0, 0, 0 }
  4676. };
  4677. static const char **optargs[] = {
  4678. &index_option
  4679. };
  4680. static const char *help[] = {
  4681. "Specify adapter index\n"
  4682. };
  4683. static const struct bt_shell_opt opt = {
  4684. .options = main_options,
  4685. .optno = sizeof(main_options) / sizeof(struct option),
  4686. .optstr = "i:V",
  4687. .optarg = optargs,
  4688. .help = help,
  4689. };
  4690. int main(int argc, char *argv[])
  4691. {
  4692. int status;
  4693. bt_shell_init(argc, argv, &opt);
  4694. bt_shell_set_menu(&main_menu);
  4695. bt_shell_add_submenu(&monitor_menu);
  4696. mgmt = mgmt_new_default();
  4697. if (!mgmt) {
  4698. fprintf(stderr, "Unable to open mgmt_socket\n");
  4699. return EXIT_FAILURE;
  4700. }
  4701. if (getenv("MGMT_DEBUG"))
  4702. mgmt_set_debug(mgmt, mgmt_debug, "mgmt: ", NULL);
  4703. if (index_option)
  4704. set_index(index_option);
  4705. register_mgmt_callbacks(mgmt, mgmt_index);
  4706. bt_shell_attach(fileno(stdin));
  4707. update_prompt(mgmt_index);
  4708. status = bt_shell_run();
  4709. mgmt_cancel_all(mgmt);
  4710. mgmt_unregister_all(mgmt);
  4711. mgmt_unref(mgmt);
  4712. return status;
  4713. }