| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2001-2002 Nokia Corporation
- * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
- * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
- * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
- * Copyright (C) 2002-2003 Jean Tourrilhes <jt@hpl.hp.com>
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <errno.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <getopt.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include "lib/bluetooth.h"
- #include "lib/hci.h"
- #include "lib/hci_lib.h"
- #include "lib/sdp.h"
- #include "lib/sdp_lib.h"
- #include "src/sdp-xml.h"
- #ifndef APPLE_AGENT_SVCLASS_ID
- #define APPLE_AGENT_SVCLASS_ID 0x2112
- #endif
- #define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1)
- #define N_ELEMENTS(x) (sizeof(x) / sizeof((x)[0]))
- /*
- * Convert a string to a BDADDR, with a few "enhancements" - Jean II
- */
- static int estr2ba(char *str, bdaddr_t *ba)
- {
- /* Only trap "local", "any" is already dealt with */
- if(!strcmp(str, "local")) {
- bacpy(ba, BDADDR_LOCAL);
- return 0;
- }
- return str2ba(str, ba);
- }
- #define DEFAULT_VIEW 0 /* Display only known attribute */
- #define TREE_VIEW 1 /* Display full attribute tree */
- #define RAW_VIEW 2 /* Display raw tree */
- #define XML_VIEW 3 /* Display xml tree */
- /* Pass args to the inquiry/search handler */
- struct search_context {
- char *svc; /* Service */
- uuid_t group; /* Browse group */
- int view; /* View mode */
- uint32_t handle; /* Service record handle */
- };
- typedef int (*handler_t)(bdaddr_t *bdaddr, struct search_context *arg);
- static char UUID_str[MAX_LEN_UUID_STR];
- static bdaddr_t interface;
- /* Definition of attribute members */
- struct member_def {
- char *name;
- };
- /* Definition of an attribute */
- struct attrib_def {
- int num; /* Numeric ID - 16 bits */
- char *name; /* User readable name */
- struct member_def *members; /* Definition of attribute args */
- int member_max; /* Max of attribute arg definitions */
- };
- /* Definition of a service or protocol */
- struct uuid_def {
- int num; /* Numeric ID - 16 bits */
- char *name; /* User readable name */
- struct attrib_def *attribs; /* Specific attribute definitions */
- int attrib_max; /* Max of attribute definitions */
- };
- /* Context information about current attribute */
- struct attrib_context {
- struct uuid_def *service; /* Service UUID, if known */
- struct attrib_def *attrib; /* Description of the attribute */
- int member_index; /* Index of current attribute member */
- };
- /* Context information about the whole service */
- struct service_context {
- struct uuid_def *service; /* Service UUID, if known */
- };
- /* Allow us to do nice formatting of the lists */
- static char *indent_spaces = " ";
- /* ID of the service attribute.
- * Most attributes after 0x200 are defined based on the service, so
- * we need to find what is the service (which is messy) - Jean II */
- #define SERVICE_ATTR 0x1
- /* Definition of the optional arguments in protocol list */
- static struct member_def protocol_members[] = {
- { "Protocol" },
- { "Channel/Port" },
- { "Version" },
- };
- /* Definition of the optional arguments in profile list */
- static struct member_def profile_members[] = {
- { "Profile" },
- { "Version" },
- };
- /* Definition of the optional arguments in Language list */
- static struct member_def language_members[] = {
- { "Code ISO639" },
- { "Encoding" },
- { "Base Offset" },
- };
- /* Name of the various common attributes. See BT assigned numbers */
- static struct attrib_def attrib_names[] = {
- { 0x0, "ServiceRecordHandle", NULL, 0 },
- { 0x1, "ServiceClassIDList", NULL, 0 },
- { 0x2, "ServiceRecordState", NULL, 0 },
- { 0x3, "ServiceID", NULL, 0 },
- { 0x4, "ProtocolDescriptorList",
- protocol_members, N_ELEMENTS(protocol_members) },
- { 0x5, "BrowseGroupList", NULL, 0 },
- { 0x6, "LanguageBaseAttributeIDList",
- language_members, N_ELEMENTS(language_members) },
- { 0x7, "ServiceInfoTimeToLive", NULL, 0 },
- { 0x8, "ServiceAvailability", NULL, 0 },
- { 0x9, "BluetoothProfileDescriptorList",
- profile_members, N_ELEMENTS(profile_members) },
- { 0xA, "DocumentationURL", NULL, 0 },
- { 0xB, "ClientExecutableURL", NULL, 0 },
- { 0xC, "IconURL", NULL, 0 },
- { 0xD, "AdditionalProtocolDescriptorLists", NULL, 0 },
- /* Definitions after that are tricky (per profile or offset) */
- };
- const int attrib_max = N_ELEMENTS(attrib_names);
- /* Name of the various SPD attributes. See BT assigned numbers */
- static struct attrib_def sdp_attrib_names[] = {
- { 0x200, "VersionNumberList", NULL, 0 },
- { 0x201, "ServiceDatabaseState", NULL, 0 },
- };
- /* Name of the various SPD attributes. See BT assigned numbers */
- static struct attrib_def browse_attrib_names[] = {
- { 0x200, "GroupID", NULL, 0 },
- };
- /* Name of the various Device ID attributes. See Device Id spec. */
- static struct attrib_def did_attrib_names[] = {
- { 0x200, "SpecificationID", NULL, 0 },
- { 0x201, "VendorID", NULL, 0 },
- { 0x202, "ProductID", NULL, 0 },
- { 0x203, "Version", NULL, 0 },
- { 0x204, "PrimaryRecord", NULL, 0 },
- { 0x205, "VendorIDSource", NULL, 0 },
- };
- /* Name of the various HID attributes. See HID spec. */
- static struct attrib_def hid_attrib_names[] = {
- { 0x200, "DeviceReleaseNum", NULL, 0 },
- { 0x201, "ParserVersion", NULL, 0 },
- { 0x202, "DeviceSubclass", NULL, 0 },
- { 0x203, "CountryCode", NULL, 0 },
- { 0x204, "VirtualCable", NULL, 0 },
- { 0x205, "ReconnectInitiate", NULL, 0 },
- { 0x206, "DescriptorList", NULL, 0 },
- { 0x207, "LangIDBaseList", NULL, 0 },
- { 0x208, "SDPDisable", NULL, 0 },
- { 0x209, "BatteryPower", NULL, 0 },
- { 0x20a, "RemoteWakeup", NULL, 0 },
- { 0x20b, "ProfileVersion", NULL, 0 },
- { 0x20c, "SupervisionTimeout", NULL, 0 },
- { 0x20d, "NormallyConnectable", NULL, 0 },
- { 0x20e, "BootDevice", NULL, 0 },
- };
- /* Name of the various PAN attributes. See BT assigned numbers */
- /* Note : those need to be double checked - Jean II */
- static struct attrib_def pan_attrib_names[] = {
- { 0x200, "IpSubnet", NULL, 0 }, /* Obsolete ??? */
- { 0x30A, "SecurityDescription", NULL, 0 },
- { 0x30B, "NetAccessType", NULL, 0 },
- { 0x30C, "MaxNetAccessrate", NULL, 0 },
- { 0x30D, "IPv4Subnet", NULL, 0 },
- { 0x30E, "IPv6Subnet", NULL, 0 },
- };
- /* Name of the various Generic-Audio attributes. See BT assigned numbers */
- /* Note : totally untested - Jean II */
- static struct attrib_def audio_attrib_names[] = {
- { 0x302, "Remote audio volume control", NULL, 0 },
- };
- /* Name of the various IrMCSync attributes. See BT assigned numbers */
- static struct attrib_def irmc_attrib_names[] = {
- { 0x0301, "SupportedDataStoresList", NULL, 0 },
- };
- /* Name of the various GOEP attributes. See BT assigned numbers */
- static struct attrib_def goep_attrib_names[] = {
- { 0x200, "GoepL2capPsm", NULL, 0 },
- };
- /* Name of the various PBAP attributes. See BT assigned numbers */
- static struct attrib_def pbap_attrib_names[] = {
- { 0x0314, "SupportedRepositories", NULL, 0 },
- { 0x0317, "PbapSupportedFeatures", NULL, 0 },
- };
- /* Name of the various MAS attributes. See BT assigned numbers */
- static struct attrib_def mas_attrib_names[] = {
- { 0x0315, "MASInstanceID", NULL, 0 },
- { 0x0316, "SupportedMessageTypes", NULL, 0 },
- { 0x0317, "MapSupportedFeatures", NULL, 0 },
- };
- /* Name of the various MNS attributes. See BT assigned numbers */
- static struct attrib_def mns_attrib_names[] = {
- { 0x0317, "MapSupportedFeatures", NULL, 0 },
- };
- /* Same for the UUIDs. See BT assigned numbers */
- static struct uuid_def uuid16_names[] = {
- /* -- Protocols -- */
- { 0x0001, "SDP", NULL, 0 },
- { 0x0002, "UDP", NULL, 0 },
- { 0x0003, "RFCOMM", NULL, 0 },
- { 0x0004, "TCP", NULL, 0 },
- { 0x0005, "TCS-BIN", NULL, 0 },
- { 0x0006, "TCS-AT", NULL, 0 },
- { 0x0008, "OBEX", NULL, 0 },
- { 0x0009, "IP", NULL, 0 },
- { 0x000a, "FTP", NULL, 0 },
- { 0x000c, "HTTP", NULL, 0 },
- { 0x000e, "WSP", NULL, 0 },
- { 0x000f, "BNEP", NULL, 0 },
- { 0x0010, "UPnP/ESDP", NULL, 0 },
- { 0x0011, "HIDP", NULL, 0 },
- { 0x0012, "HardcopyControlChannel", NULL, 0 },
- { 0x0014, "HardcopyDataChannel", NULL, 0 },
- { 0x0016, "HardcopyNotification", NULL, 0 },
- { 0x0017, "AVCTP", NULL, 0 },
- { 0x0019, "AVDTP", NULL, 0 },
- { 0x001b, "CMTP", NULL, 0 },
- { 0x001d, "UDI_C-Plane", NULL, 0 },
- { 0x0100, "L2CAP", NULL, 0 },
- /* -- Services -- */
- { 0x1000, "ServiceDiscoveryServerServiceClassID",
- sdp_attrib_names, N_ELEMENTS(sdp_attrib_names) },
- { 0x1001, "BrowseGroupDescriptorServiceClassID",
- browse_attrib_names, N_ELEMENTS(browse_attrib_names) },
- { 0x1002, "PublicBrowseGroup", NULL, 0 },
- { 0x1101, "SerialPort", NULL, 0 },
- { 0x1102, "LANAccessUsingPPP", NULL, 0 },
- { 0x1103, "DialupNetworking (DUN)", NULL, 0 },
- { 0x1104, "IrMCSync",
- irmc_attrib_names, N_ELEMENTS(irmc_attrib_names) },
- { 0x1105, "OBEXObjectPush",
- goep_attrib_names, N_ELEMENTS(goep_attrib_names) },
- { 0x1106, "OBEXFileTransfer",
- goep_attrib_names, N_ELEMENTS(goep_attrib_names) },
- { 0x1107, "IrMCSyncCommand", NULL, 0 },
- { 0x1108, "Headset",
- audio_attrib_names, N_ELEMENTS(audio_attrib_names) },
- { 0x1109, "CordlessTelephony", NULL, 0 },
- { 0x110a, "AudioSource", NULL, 0 },
- { 0x110b, "AudioSink", NULL, 0 },
- { 0x110c, "RemoteControlTarget", NULL, 0 },
- { 0x110d, "AdvancedAudio", NULL, 0 },
- { 0x110e, "RemoteControl", NULL, 0 },
- { 0x110f, "RemoteControlController", NULL, 0 },
- { 0x1110, "Intercom", NULL, 0 },
- { 0x1111, "Fax", NULL, 0 },
- { 0x1112, "HeadsetAudioGateway", NULL, 0 },
- { 0x1113, "WAP", NULL, 0 },
- { 0x1114, "WAP Client", NULL, 0 },
- { 0x1115, "PANU (PAN/BNEP)",
- pan_attrib_names, N_ELEMENTS(pan_attrib_names) },
- { 0x1116, "NAP (PAN/BNEP)",
- pan_attrib_names, N_ELEMENTS(pan_attrib_names) },
- { 0x1117, "GN (PAN/BNEP)",
- pan_attrib_names, N_ELEMENTS(pan_attrib_names) },
- { 0x1118, "DirectPrinting (BPP)", NULL, 0 },
- { 0x1119, "ReferencePrinting (BPP)", NULL, 0 },
- { 0x111a, "Imaging (BIP)", NULL, 0 },
- { 0x111b, "ImagingResponder (BIP)", NULL, 0 },
- { 0x111c, "ImagingAutomaticArchive (BIP)", NULL, 0 },
- { 0x111d, "ImagingReferencedObjects (BIP)", NULL, 0 },
- { 0x111e, "Handsfree", NULL, 0 },
- { 0x111f, "HandsfreeAudioGateway", NULL, 0 },
- { 0x1120, "DirectPrintingReferenceObjectsService (BPP)", NULL, 0 },
- { 0x1121, "ReflectedUI (BPP)", NULL, 0 },
- { 0x1122, "BasicPrinting (BPP)", NULL, 0 },
- { 0x1123, "PrintingStatus (BPP)", NULL, 0 },
- { 0x1124, "HumanInterfaceDeviceService (HID)",
- hid_attrib_names, N_ELEMENTS(hid_attrib_names) },
- { 0x1125, "HardcopyCableReplacement (HCR)", NULL, 0 },
- { 0x1126, "HCR_Print (HCR)", NULL, 0 },
- { 0x1127, "HCR_Scan (HCR)", NULL, 0 },
- { 0x1128, "Common ISDN Access (CIP)", NULL, 0 },
- { 0x112a, "UDI-MT", NULL, 0 },
- { 0x112b, "UDI-TA", NULL, 0 },
- { 0x112c, "Audio/Video", NULL, 0 },
- { 0x112d, "SIM Access (SAP)", NULL, 0 },
- { 0x112e, "Phonebook Access (PBAP) - PCE", NULL, 0 },
- { 0x112f, "Phonebook Access (PBAP) - PSE",
- pbap_attrib_names, N_ELEMENTS(pbap_attrib_names) },
- { 0x1130, "Phonebook Access (PBAP)", NULL, 0 },
- { 0x1131, "Headset (HSP)", NULL, 0 },
- { 0x1132, "Message Access (MAP) - MAS",
- mas_attrib_names, N_ELEMENTS(mas_attrib_names) },
- { 0x1133, "Message Access (MAP) - MNS",
- mns_attrib_names, N_ELEMENTS(mns_attrib_names) },
- { 0x1134, "Message Access (MAP)", NULL, 0 },
- /* ... */
- { 0x1200, "PnPInformation",
- did_attrib_names, N_ELEMENTS(did_attrib_names) },
- { 0x1201, "GenericNetworking", NULL, 0 },
- { 0x1202, "GenericFileTransfer", NULL, 0 },
- { 0x1203, "GenericAudio",
- audio_attrib_names, N_ELEMENTS(audio_attrib_names) },
- { 0x1204, "GenericTelephony", NULL, 0 },
- /* ... */
- { 0x1303, "VideoSource", NULL, 0 },
- { 0x1304, "VideoSink", NULL, 0 },
- { 0x1305, "VideoDistribution", NULL, 0 },
- { 0x1400, "HDP", NULL, 0 },
- { 0x1401, "HDPSource", NULL, 0 },
- { 0x1402, "HDPSink", NULL, 0 },
- { 0x2112, "AppleAgent", NULL, 0 },
- };
- static const int uuid16_max = N_ELEMENTS(uuid16_names);
- static void sdp_data_printf(sdp_data_t *, struct attrib_context *, int);
- /*
- * Parse a UUID.
- * The BT assigned numbers only list UUID16, so I'm not sure the
- * other types will ever get used...
- */
- static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent)
- {
- if (uuid) {
- if (uuid->type == SDP_UUID16) {
- uint16_t uuidNum = uuid->value.uuid16;
- struct uuid_def *uuidDef = NULL;
- int i;
- for (i = 0; i < uuid16_max; i++)
- if (uuid16_names[i].num == uuidNum) {
- uuidDef = &uuid16_names[i];
- break;
- }
- /* Check if it's the service attribute */
- if (context->attrib && context->attrib->num == SERVICE_ATTR) {
- /* We got the service ID !!! */
- context->service = uuidDef;
- }
- if (uuidDef)
- printf("%.*sUUID16 : 0x%.4x - %s\n",
- indent, indent_spaces, uuidNum, uuidDef->name);
- else
- printf("%.*sUUID16 : 0x%.4x\n",
- indent, indent_spaces, uuidNum);
- } else if (uuid->type == SDP_UUID32) {
- struct uuid_def *uuidDef = NULL;
- int i;
- if (!(uuid->value.uuid32 & 0xffff0000)) {
- uint16_t uuidNum = uuid->value.uuid32;
- for (i = 0; i < uuid16_max; i++)
- if (uuid16_names[i].num == uuidNum) {
- uuidDef = &uuid16_names[i];
- break;
- }
- }
- if (uuidDef)
- printf("%.*sUUID32 : 0x%.8x - %s\n",
- indent, indent_spaces, uuid->value.uuid32, uuidDef->name);
- else
- printf("%.*sUUID32 : 0x%.8x\n",
- indent, indent_spaces, uuid->value.uuid32);
- } else if (uuid->type == SDP_UUID128) {
- unsigned int data0;
- unsigned short data1;
- unsigned short data2;
- unsigned short data3;
- unsigned int data4;
- unsigned short data5;
- memcpy(&data0, &uuid->value.uuid128.data[0], 4);
- memcpy(&data1, &uuid->value.uuid128.data[4], 2);
- memcpy(&data2, &uuid->value.uuid128.data[6], 2);
- memcpy(&data3, &uuid->value.uuid128.data[8], 2);
- memcpy(&data4, &uuid->value.uuid128.data[10], 4);
- memcpy(&data5, &uuid->value.uuid128.data[14], 2);
- printf("%.*sUUID128 : 0x%.8x-%.4x-%.4x-%.4x-%.8x-%.4x\n",
- indent, indent_spaces,
- ntohl(data0), ntohs(data1), ntohs(data2),
- ntohs(data3), ntohl(data4), ntohs(data5));
- } else
- printf("%.*sEnum type of UUID not set\n",
- indent, indent_spaces);
- } else
- printf("%.*sNull passed to print UUID\n",
- indent, indent_spaces);
- }
- /*
- * Parse a sequence of data elements (i.e. a list)
- */
- static void printf_dataseq(sdp_data_t * pData, struct attrib_context *context, int indent)
- {
- sdp_data_t *sdpdata = NULL;
- sdpdata = pData;
- if (sdpdata) {
- context->member_index = 0;
- do {
- sdp_data_printf(sdpdata, context, indent + 2);
- sdpdata = sdpdata->next;
- context->member_index++;
- } while (sdpdata);
- } else {
- printf("%.*sBroken dataseq link\n", indent, indent_spaces);
- }
- }
- /*
- * Parse a single data element (either in the attribute or in a data
- * sequence).
- */
- static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent)
- {
- char *member_name = NULL;
- /* Find member name. Almost black magic ;-) */
- if (context && context->attrib && context->attrib->members &&
- context->member_index < context->attrib->member_max) {
- member_name = context->attrib->members[context->member_index].name;
- }
- switch (sdpdata->dtd) {
- case SDP_DATA_NIL:
- printf("%.*sNil\n", indent, indent_spaces);
- break;
- case SDP_BOOL:
- case SDP_UINT8:
- case SDP_UINT16:
- case SDP_UINT32:
- case SDP_UINT64:
- case SDP_UINT128:
- case SDP_INT8:
- case SDP_INT16:
- case SDP_INT32:
- case SDP_INT64:
- case SDP_INT128:
- if (member_name) {
- printf("%.*s%s (Integer) : 0x%x\n",
- indent, indent_spaces, member_name, sdpdata->val.uint32);
- } else {
- printf("%.*sInteger : 0x%x\n", indent, indent_spaces,
- sdpdata->val.uint32);
- }
- break;
- case SDP_UUID16:
- case SDP_UUID32:
- case SDP_UUID128:
- //printf("%.*sUUID\n", indent, indent_spaces);
- sdp_uuid_printf(&sdpdata->val.uuid, context, indent);
- break;
- case SDP_TEXT_STR8:
- case SDP_TEXT_STR16:
- case SDP_TEXT_STR32:
- if (sdpdata->unitSize > (int) strlen(sdpdata->val.str)) {
- int i;
- printf("%.*sData :", indent, indent_spaces);
- for (i = 0; i < sdpdata->unitSize; i++)
- printf(" %02x", (unsigned char) sdpdata->val.str[i]);
- printf("\n");
- } else
- printf("%.*sText : \"%s\"\n", indent, indent_spaces, sdpdata->val.str);
- break;
- case SDP_URL_STR8:
- case SDP_URL_STR16:
- case SDP_URL_STR32:
- printf("%.*sURL : %s\n", indent, indent_spaces, sdpdata->val.str);
- break;
- case SDP_SEQ8:
- case SDP_SEQ16:
- case SDP_SEQ32:
- printf("%.*sData Sequence\n", indent, indent_spaces);
- printf_dataseq(sdpdata->val.dataseq, context, indent);
- break;
- case SDP_ALT8:
- case SDP_ALT16:
- case SDP_ALT32:
- printf("%.*sData Sequence Alternates\n", indent, indent_spaces);
- printf_dataseq(sdpdata->val.dataseq, context, indent);
- break;
- }
- }
- /*
- * Parse a single attribute.
- */
- static void print_tree_attr_func(void *value, void *userData)
- {
- sdp_data_t *sdpdata = value;
- uint16_t attrId;
- struct service_context *service = (struct service_context *) userData;
- struct attrib_context context;
- struct attrib_def *attrDef = NULL;
- int i;
- if (!sdpdata)
- return;
- attrId = sdpdata->attrId;
- /* Search amongst the generic attributes */
- for (i = 0; i < attrib_max; i++)
- if (attrib_names[i].num == attrId) {
- attrDef = &attrib_names[i];
- break;
- }
- /* Search amongst the specific attributes of this service */
- if ((attrDef == NULL) && (service->service != NULL) &&
- (service->service->attribs != NULL)) {
- struct attrib_def *svc_attribs = service->service->attribs;
- int svc_attrib_max = service->service->attrib_max;
- for (i = 0; i < svc_attrib_max; i++)
- if (svc_attribs[i].num == attrId) {
- attrDef = &svc_attribs[i];
- break;
- }
- }
- if (attrDef)
- printf("Attribute Identifier : 0x%x - %s\n", attrId, attrDef->name);
- else
- printf("Attribute Identifier : 0x%x\n", attrId);
- /* Build context */
- context.service = service->service;
- context.attrib = attrDef;
- context.member_index = 0;
- /* Parse attribute members */
- sdp_data_printf(sdpdata, &context, 2);
- /* Update service */
- service->service = context.service;
- }
- /*
- * Main entry point of this library. Parse a SDP record.
- * We assume the record has already been read, parsed and cached
- * locally. Jean II
- */
- static void print_tree_attr(sdp_record_t *rec)
- {
- if (rec && rec->attrlist) {
- struct service_context service = { NULL };
- sdp_list_foreach(rec->attrlist, print_tree_attr_func, &service);
- }
- }
- static void print_raw_data(sdp_data_t *data, int indent)
- {
- struct uuid_def *def;
- int i, hex;
- if (!data)
- return;
- for (i = 0; i < indent; i++)
- printf("\t");
- switch (data->dtd) {
- case SDP_DATA_NIL:
- printf("NIL\n");
- break;
- case SDP_BOOL:
- printf("Bool %s\n", data->val.uint8 ? "True" : "False");
- break;
- case SDP_UINT8:
- printf("UINT8 0x%02x\n", data->val.uint8);
- break;
- case SDP_UINT16:
- printf("UINT16 0x%04x\n", data->val.uint16);
- break;
- case SDP_UINT32:
- printf("UINT32 0x%08x\n", data->val.uint32);
- break;
- case SDP_UINT64:
- printf("UINT64 0x%016jx\n", data->val.uint64);
- break;
- case SDP_UINT128:
- printf("UINT128 ...\n");
- break;
- case SDP_INT8:
- printf("INT8 %d\n", data->val.int8);
- break;
- case SDP_INT16:
- printf("INT16 %d\n", data->val.int16);
- break;
- case SDP_INT32:
- printf("INT32 %d\n", data->val.int32);
- break;
- case SDP_INT64:
- printf("INT64 %jd\n", data->val.int64);
- break;
- case SDP_INT128:
- printf("INT128 ...\n");
- break;
- case SDP_UUID16:
- case SDP_UUID32:
- case SDP_UUID128:
- switch (data->val.uuid.type) {
- case SDP_UUID16:
- def = NULL;
- for (i = 0; i < uuid16_max; i++)
- if (uuid16_names[i].num == data->val.uuid.value.uuid16) {
- def = &uuid16_names[i];
- break;
- }
- if (def)
- printf("UUID16 0x%04x - %s\n", data->val.uuid.value.uuid16, def->name);
- else
- printf("UUID16 0x%04x\n", data->val.uuid.value.uuid16);
- break;
- case SDP_UUID32:
- def = NULL;
- if (!(data->val.uuid.value.uuid32 & 0xffff0000)) {
- uint16_t value = data->val.uuid.value.uuid32;
- for (i = 0; i < uuid16_max; i++)
- if (uuid16_names[i].num == value) {
- def = &uuid16_names[i];
- break;
- }
- }
- if (def)
- printf("UUID32 0x%08x - %s\n", data->val.uuid.value.uuid32, def->name);
- else
- printf("UUID32 0x%08x\n", data->val.uuid.value.uuid32);
- break;
- case SDP_UUID128:
- printf("UUID128 ");
- for (i = 0; i < 16; i++) {
- switch (i) {
- case 4:
- case 6:
- case 8:
- case 10:
- printf("-");
- break;
- }
- printf("%02x", (unsigned char ) data->val.uuid.value.uuid128.data[i]);
- }
- printf("\n");
- break;
- default:
- printf("UUID type 0x%02x\n", data->val.uuid.type);
- break;
- }
- break;
- case SDP_TEXT_STR8:
- case SDP_TEXT_STR16:
- case SDP_TEXT_STR32:
- hex = 0;
- for (i = 0; i < data->unitSize; i++) {
- if (i == (data->unitSize - 1) && data->val.str[i] == '\0')
- break;
- if (!isprint(data->val.str[i])) {
- hex = 1;
- break;
- }
- }
- if (hex) {
- printf("Data");
- for (i = 0; i < data->unitSize; i++)
- printf(" %02x", (unsigned char) data->val.str[i]);
- } else {
- printf("String ");
- for (i = 0; i < data->unitSize; i++)
- printf("%c", data->val.str[i]);
- }
- printf("\n");
- break;
- case SDP_URL_STR8:
- case SDP_URL_STR16:
- case SDP_URL_STR32:
- printf("URL %s\n", data->val.str);
- break;
- case SDP_SEQ8:
- case SDP_SEQ16:
- case SDP_SEQ32:
- printf("Sequence\n");
- print_raw_data(data->val.dataseq, indent + 1);
- break;
- case SDP_ALT8:
- case SDP_ALT16:
- case SDP_ALT32:
- printf("Alternate\n");
- print_raw_data(data->val.dataseq, indent + 1);
- break;
- default:
- printf("Unknown type 0x%02x\n", data->dtd);
- break;
- }
- print_raw_data(data->next, indent);
- }
- static void print_raw_attr_func(void *value, void *userData)
- {
- sdp_data_t *data = (sdp_data_t *) value;
- struct attrib_def *def = NULL;
- int i;
- if (!data)
- return;
- /* Search amongst the generic attributes */
- for (i = 0; i < attrib_max; i++)
- if (attrib_names[i].num == data->attrId) {
- def = &attrib_names[i];
- break;
- }
- if (def)
- printf("\tAttribute 0x%04x - %s\n", data->attrId, def->name);
- else
- printf("\tAttribute 0x%04x\n", data->attrId);
- print_raw_data(data, 2);
- }
- static void print_raw_attr(sdp_record_t *rec)
- {
- if (rec && rec->attrlist) {
- printf("Sequence\n");
- sdp_list_foreach(rec->attrlist, print_raw_attr_func, 0);
- }
- }
- /*
- * Set attributes with single values in SDP record
- * Jean II
- */
- static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *value)
- {
- sdp_list_t *attrid_list;
- uint32_t range = 0x0000ffff;
- sdp_record_t *rec;
- int ret;
- /* Get the old SDP record */
- attrid_list = sdp_list_append(NULL, &range);
- rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attrid_list);
- sdp_list_free(attrid_list, NULL);
- if (!rec) {
- printf("Service get request failed.\n");
- return -1;
- }
- /* Check the type of attribute */
- if (!strncasecmp(value, "u0x", 3)) {
- /* UUID16 */
- uint16_t value_int = 0;
- uuid_t value_uuid;
- value_int = strtoul(value + 3, NULL, 16);
- sdp_uuid16_create(&value_uuid, value_int);
- printf("Adding attrib 0x%X uuid16 0x%X to record 0x%X\n",
- attrib, value_int, handle);
- sdp_attr_add_new(rec, attrib, SDP_UUID16, &value_uuid.value.uuid16);
- } else if (!strncasecmp(value, "0x", 2)) {
- /* Int */
- uint32_t value_int;
- value_int = strtoul(value + 2, NULL, 16);
- printf("Adding attrib 0x%X int 0x%X to record 0x%X\n",
- attrib, value_int, handle);
- sdp_attr_add_new(rec, attrib, SDP_UINT32, &value_int);
- } else {
- /* String */
- printf("Adding attrib 0x%X string \"%s\" to record 0x%X\n",
- attrib, value, handle);
- /* Add/Update our attribute to the record */
- sdp_attr_add_new(rec, attrib, SDP_TEXT_STR8, value);
- }
- /* Update on the server */
- ret = sdp_device_record_update(sess, &interface, rec);
- if (ret < 0)
- printf("Service Record update failed (%d).\n", errno);
- sdp_record_free(rec);
- return ret;
- }
- static struct option set_options[] = {
- { "help", 0, 0, 'h' },
- { 0, 0, 0, 0 }
- };
- static const char *set_help =
- "Usage:\n"
- "\tget record_handle attrib_id attrib_value\n";
- /*
- * Add an attribute to an existing SDP record on the local SDP server
- */
- static int cmd_setattr(int argc, char **argv)
- {
- int opt, status;
- uint32_t handle;
- uint16_t attrib;
- sdp_session_t *sess;
- for_each_opt(opt, set_options, NULL) {
- switch(opt) {
- default:
- printf("%s", set_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 3) {
- printf("%s", set_help);
- return -1;
- }
- /* Convert command line args */
- handle = strtoul(argv[0], NULL, 16);
- attrib = strtoul(argv[1], NULL, 16);
- /* Do it */
- sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
- if (!sess)
- return -1;
- status = set_attrib(sess, handle, attrib, argv[2]);
- sdp_close(sess);
- return status;
- }
- /*
- * We do only simple data sequences. Sequence of sequences is a pain ;-)
- * Jean II
- */
- static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int argc, char **argv)
- {
- sdp_list_t *attrid_list;
- uint32_t range = 0x0000ffff;
- sdp_record_t *rec;
- sdp_data_t *pSequenceHolder = NULL;
- void **dtdArray;
- void **valueArray;
- void **allocArray;
- uint8_t uuid16 = SDP_UUID16;
- uint8_t uint32 = SDP_UINT32;
- uint8_t str8 = SDP_TEXT_STR8;
- int i, ret = 0;
- /* Get the old SDP record */
- attrid_list = sdp_list_append(NULL, &range);
- rec = sdp_service_attr_req(session, handle, SDP_ATTR_REQ_RANGE, attrid_list);
- sdp_list_free(attrid_list, NULL);
- if (!rec) {
- printf("Service get request failed.\n");
- return -1;
- }
- /* Create arrays */
- dtdArray = malloc(argc * sizeof(void *));
- valueArray = malloc(argc * sizeof(void *));
- allocArray = malloc(argc * sizeof(void *));
- if (!dtdArray || !valueArray || !allocArray) {
- ret = -ENOMEM;
- goto cleanup;
- }
- /* Loop on all args, add them in arrays */
- for (i = 0; i < argc; i++) {
- /* Check the type of attribute */
- if (!strncasecmp(argv[i], "u0x", 3)) {
- /* UUID16 */
- uint16_t value_int = strtoul((argv[i]) + 3, NULL, 16);
- uuid_t *value_uuid = malloc(sizeof(uuid_t));
- if (!value_uuid) {
- ret = -ENOMEM;
- goto cleanup;
- }
- allocArray[i] = value_uuid;
- sdp_uuid16_create(value_uuid, value_int);
- printf("Adding uuid16 0x%X to record 0x%X\n", value_int, handle);
- dtdArray[i] = &uuid16;
- valueArray[i] = &value_uuid->value.uuid16;
- } else if (!strncasecmp(argv[i], "0x", 2)) {
- /* Int */
- uint32_t *value_int = malloc(sizeof(int));
- if (!value_int) {
- ret = -ENOMEM;
- goto cleanup;
- }
- allocArray[i] = value_int;
- *value_int = strtoul((argv[i]) + 2, NULL, 16);
- printf("Adding int 0x%X to record 0x%X\n", *value_int, handle);
- dtdArray[i] = &uint32;
- valueArray[i] = value_int;
- } else {
- /* String */
- printf("Adding string \"%s\" to record 0x%X\n", argv[i], handle);
- dtdArray[i] = &str8;
- valueArray[i] = argv[i];
- }
- }
- /* Add this sequence to the attrib list */
- pSequenceHolder = sdp_seq_alloc(dtdArray, valueArray, argc);
- if (pSequenceHolder) {
- sdp_attr_replace(rec, attrib, pSequenceHolder);
- /* Update on the server */
- ret = sdp_device_record_update(session, &interface, rec);
- if (ret < 0)
- printf("Service Record update failed (%d).\n", errno);
- } else
- printf("Failed to create pSequenceHolder\n");
- cleanup:
- if (ret == -ENOMEM)
- printf("Memory allocation failed\n");
- /* Cleanup */
- for (i = 0; i < argc; i++)
- if (allocArray)
- free(allocArray[i]);
- free(dtdArray);
- free(valueArray);
- free(allocArray);
- sdp_record_free(rec);
- return ret;
- }
- static struct option seq_options[] = {
- { "help", 0, 0, 'h' },
- { 0, 0, 0, 0 }
- };
- static const char *seq_help =
- "Usage:\n"
- "\tget record_handle attrib_id attrib_values\n";
- /*
- * Add an attribute sequence to an existing SDP record
- * on the local SDP server
- */
- static int cmd_setseq(int argc, char **argv)
- {
- int opt, status;
- uint32_t handle;
- uint16_t attrib;
- sdp_session_t *sess;
- for_each_opt(opt, seq_options, NULL) {
- switch(opt) {
- default:
- printf("%s", seq_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 3) {
- printf("%s", seq_help);
- return -1;
- }
- /* Convert command line args */
- handle = strtoul(argv[0], NULL, 16);
- attrib = strtoul(argv[1], NULL, 16);
- argc -= 2;
- argv += 2;
- /* Do it */
- sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
- if (!sess)
- return -1;
- status = set_attribseq(sess, handle, attrib, argc, argv);
- sdp_close(sess);
- return status;
- }
- static void print_service_class(void *value, void *userData)
- {
- char ServiceClassUUID_str[MAX_LEN_SERVICECLASS_UUID_STR];
- uuid_t *uuid = (uuid_t *)value;
- sdp_uuid2strn(uuid, UUID_str, MAX_LEN_UUID_STR);
- sdp_svclass_uuid2strn(uuid, ServiceClassUUID_str, MAX_LEN_SERVICECLASS_UUID_STR);
- if (uuid->type != SDP_UUID128)
- printf(" \"%s\" (0x%s)\n", ServiceClassUUID_str, UUID_str);
- else
- printf(" UUID 128: %s\n", UUID_str);
- }
- static void print_service_desc(void *value, void *user)
- {
- char str[MAX_LEN_PROTOCOL_UUID_STR];
- sdp_data_t *p = (sdp_data_t *)value, *s;
- int i = 0, proto = 0;
- for (; p; p = p->next, i++) {
- switch (p->dtd) {
- case SDP_UUID16:
- case SDP_UUID32:
- case SDP_UUID128:
- sdp_uuid2strn(&p->val.uuid, UUID_str, MAX_LEN_UUID_STR);
- sdp_proto_uuid2strn(&p->val.uuid, str, sizeof(str));
- proto = sdp_uuid_to_proto(&p->val.uuid);
- printf(" \"%s\" (0x%s)\n", str, UUID_str);
- break;
- case SDP_UINT8:
- if (proto == RFCOMM_UUID)
- printf(" Channel: %d\n", p->val.uint8);
- else
- printf(" uint8: 0x%02x\n", p->val.uint8);
- break;
- case SDP_UINT16:
- if (proto == L2CAP_UUID) {
- if (i == 1)
- printf(" PSM: %d\n", p->val.uint16);
- else
- printf(" Version: 0x%04x\n", p->val.uint16);
- } else if (proto == BNEP_UUID)
- if (i == 1)
- printf(" Version: 0x%04x\n", p->val.uint16);
- else
- printf(" uint16: 0x%04x\n", p->val.uint16);
- else
- printf(" uint16: 0x%04x\n", p->val.uint16);
- break;
- case SDP_SEQ16:
- printf(" SEQ16:");
- for (s = p->val.dataseq; s; s = s->next)
- printf(" %x", s->val.uint16);
- printf("\n");
- break;
- case SDP_SEQ8:
- printf(" SEQ8:");
- for (s = p->val.dataseq; s; s = s->next)
- printf(" %x", s->val.uint8);
- printf("\n");
- break;
- default:
- printf(" FIXME: dtd=0%x\n", p->dtd);
- break;
- }
- }
- }
- static void print_lang_attr(void *value, void *user)
- {
- sdp_lang_attr_t *lang = (sdp_lang_attr_t *)value;
- printf(" code_ISO639: 0x%02x\n", lang->code_ISO639);
- printf(" encoding: 0x%02x\n", lang->encoding);
- printf(" base_offset: 0x%02x\n", lang->base_offset);
- }
- static void print_access_protos(void *value, void *userData)
- {
- sdp_list_t *protDescSeq = (sdp_list_t *)value;
- sdp_list_foreach(protDescSeq, print_service_desc, 0);
- }
- static void print_profile_desc(void *value, void *userData)
- {
- sdp_profile_desc_t *desc = (sdp_profile_desc_t *)value;
- char str[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR];
- sdp_uuid2strn(&desc->uuid, UUID_str, MAX_LEN_UUID_STR);
- sdp_profile_uuid2strn(&desc->uuid, str, MAX_LEN_PROFILEDESCRIPTOR_UUID_STR);
- printf(" \"%s\" (0x%s)\n", str, UUID_str);
- if (desc->version)
- printf(" Version: 0x%04x\n", desc->version);
- }
- /*
- * Parse a SDP record in user friendly form.
- */
- static void print_service_attr(sdp_record_t *rec)
- {
- sdp_list_t *list = 0, *proto = 0;
- sdp_record_print(rec);
- printf("Service RecHandle: 0x%x\n", rec->handle);
- if (sdp_get_service_classes(rec, &list) == 0) {
- printf("Service Class ID List:\n");
- sdp_list_foreach(list, print_service_class, 0);
- sdp_list_free(list, free);
- }
- if (sdp_get_access_protos(rec, &proto) == 0) {
- printf("Protocol Descriptor List:\n");
- sdp_list_foreach(proto, print_access_protos, 0);
- sdp_list_foreach(proto, (sdp_list_func_t)sdp_list_free, 0);
- sdp_list_free(proto, 0);
- }
- if (sdp_get_lang_attr(rec, &list) == 0) {
- printf("Language Base Attr List:\n");
- sdp_list_foreach(list, print_lang_attr, 0);
- sdp_list_free(list, free);
- }
- if (sdp_get_profile_descs(rec, &list) == 0) {
- printf("Profile Descriptor List:\n");
- sdp_list_foreach(list, print_profile_desc, 0);
- sdp_list_free(list, free);
- }
- }
- /*
- * Support for Service (de)registration
- */
- typedef struct {
- uint32_t handle;
- char *name;
- char *provider;
- char *desc;
- unsigned int class;
- unsigned int profile;
- uint16_t psm;
- uint8_t channel;
- uint8_t network;
- } svc_info_t;
- static int add_sp(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
- uuid_t root_uuid, sp_uuid, l2cap, rfcomm;
- sdp_profile_desc_t profile;
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 1;
- sdp_data_t *channel;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &sp_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
- profile.version = 0x0100;
- profiles = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, profiles);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_add_lang_attr(&record);
- sdp_set_info_attr(&record, "Serial Port", "BlueZ", "COM Port");
- sdp_set_url_attr(&record, "http://www.bluez.org/",
- "http://www.bluez.org/", "http://www.bluez.org/");
- sdp_set_service_id(&record, sp_uuid);
- sdp_set_service_ttl(&record, 0xffff);
- sdp_set_service_avail(&record, 0xff);
- sdp_set_record_state(&record, 0x00001234);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Serial Port service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, 0);
- sdp_list_free(profiles, 0);
- return ret;
- }
- static int add_dun(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto;
- uuid_t rootu, dun, gn, l2cap, rfcomm;
- sdp_profile_desc_t profile;
- sdp_list_t *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 2;
- sdp_data_t *channel;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &rootu);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &dun);
- sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &gn);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Dial-Up Networking service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_fax(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel? si->channel : 3;
- sdp_data_t *channel;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &fax_uuid);
- sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &tel_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Fax", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Fax service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_lan(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 4;
- sdp_data_t *channel;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&svclass_uuid, LAN_ACCESS_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, LAN_ACCESS_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("LAN Access service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_headset(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 5;
- sdp_data_t *channel;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Headset", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Headset service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_headset_ag(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 7;
- sdp_data_t *channel;
- uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Headset AG service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_handsfree(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 6;
- uint16_t u16 = 0x31;
- sdp_data_t *channel, *features;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
- profile.version = 0x0101;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- features = sdp_data_alloc(SDP_UINT16, &u16);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Handsfree", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Handsfree service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel : 7;
- uint16_t u16 = 0x17;
- sdp_data_t *channel, *features;
- uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
- profile.version = 0x0105;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- features = sdp_data_alloc(SDP_UINT16, &u16);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Handsfree AG service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_simaccess(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t u8 = si->channel? si->channel : 8;
- uint16_t u16 = 0x31;
- sdp_data_t *channel, *features;
- int ret = 0;
- memset((void *)&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&svclass_uuid, SAP_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID);
- profile.version = 0x0101;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- features = sdp_data_alloc(SDP_UINT16, &u16);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "SIM Access", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("SIM Access service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_opush(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t chan = si->channel ? si->channel : 9;
- sdp_data_t *channel;
- uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xff };
- void *dtds[sizeof(formats)], *values[sizeof(formats)];
- unsigned int i;
- uint8_t dtd = SDP_UINT8;
- sdp_data_t *sflist;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &opush_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &chan);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- for (i = 0; i < sizeof(formats); i++) {
- dtds[i] = &dtd;
- values[i] = &formats[i];
- }
- sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
- sdp_set_info_attr(&record, "OBEX Object Push", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("OBEX Object Push service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(pfseq, 0);
- sdp_list_free(aproto, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, NULL);
- return ret;
- }
- static int add_pbap(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, pbap_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t chan = si->channel ? si->channel : 19;
- sdp_data_t *channel;
- uint8_t formats[] = {0x01};
- uint8_t dtd = SDP_UINT8;
- sdp_data_t *sflist;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&pbap_uuid, PBAP_PSE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &pbap_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, PBAP_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &chan);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sflist = sdp_data_alloc(dtd,formats);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_REPOSITORIES, sflist);
- sdp_set_info_attr(&record, "OBEX Phonebook Access Server", 0, 0);
- if (sdp_device_record_register(session, &interface, &record,
- SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("PBAP service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(pfseq, 0);
- sdp_list_free(aproto, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, 0);
- return ret;
- }
- static int add_map(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, map_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t chan = si->channel ? si->channel : 17;
- sdp_data_t *channel;
- uint8_t msg_formats[] = {0x0f};
- uint32_t supp_features[] = {0x0000007f};
- uint8_t dtd_msg = SDP_UINT8, dtd_sf = SDP_UINT32;
- sdp_data_t *smlist;
- sdp_data_t *sflist;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&map_uuid, MAP_MSE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &map_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, MAP_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &chan);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- smlist = sdp_data_alloc(dtd_msg, msg_formats);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_MESSAGE_TYPES, smlist);
- sflist = sdp_data_alloc(dtd_sf, supp_features);
- sdp_attr_add(&record, SDP_ATTR_MAP_SUPPORTED_FEATURES, sflist);
- sdp_set_info_attr(&record, "OBEX Message Access Server", 0, 0);
- if (sdp_device_record_register(session, &interface, &record,
- SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("MAP service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(pfseq, 0);
- sdp_list_free(aproto, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, 0);
- return ret;
- }
- static int add_ftp(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t u8 = si->channel ? si->channel: 10;
- sdp_data_t *channel;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&ftrn_uuid, OBEX_FILETRANS_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, OBEX_FILETRANS_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &u8);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("OBEX File Transfer service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_directprint(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_record_t record;
- uint8_t chan = si->channel ? si->channel : 12;
- sdp_data_t *channel;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&opush_uuid, DIRECT_PRINTING_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &opush_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, BASIC_PRINTING_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &chan);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto[2] = sdp_list_append(0, &obex_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Direct Printing", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("Direct Printing service registered\n");
- end:
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(proto[2], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_nap(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t lp = 0x000f, ver = 0x0100;
- sdp_data_t *psm, *version;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&ftrn_uuid, NAP_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
- proto[1] = sdp_list_append(0, &bnep_uuid);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- {
- uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 };
- sdp_data_t *head, *pseq;
- int p;
- for (p = 0, head = NULL; p < 4; p++) {
- sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
- head = sdp_seq_append(head, data);
- }
- pseq = sdp_data_alloc(SDP_SEQ16, head);
- proto[1] = sdp_list_append(proto[1], pseq);
- }
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Network Access Point Service", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("NAP service registered\n");
- end:
- sdp_data_free(version);
- sdp_data_free(psm);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_gn(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t lp = 0x000f, ver = 0x0100;
- sdp_data_t *psm, *version;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&ftrn_uuid, GN_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
- proto[1] = sdp_list_append(0, &bnep_uuid);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Group Network Service", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("GN service registered\n");
- end:
- sdp_data_free(version);
- sdp_data_free(psm);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_panu(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t lp = 0x000f, ver = 0x0100;
- sdp_data_t *psm, *version;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
- sdp_uuid16_create(&ftrn_uuid, PANU_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &ftrn_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_list_free(svclass_id, NULL);
- sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(NULL, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_list_free(pfseq, NULL);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(NULL, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(NULL, proto[0]);
- sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
- proto[1] = sdp_list_append(NULL, &bnep_uuid);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(NULL, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "PAN User", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("PANU service registered\n");
- end:
- sdp_data_free(version);
- sdp_data_free(psm);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_hid_keyb(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
- unsigned int i;
- uint8_t dtd = SDP_UINT16;
- uint8_t dtd2 = SDP_UINT8;
- uint8_t dtd_data = SDP_TEXT_STR8;
- void *dtds[2];
- void *values[2];
- void *dtds2[2];
- void *values2[2];
- int leng[2];
- uint8_t hid_spec_type = 0x22;
- uint16_t hid_attr_lang[] = { 0x409, 0x100 };
- static const uint16_t ctrl = 0x11;
- static const uint16_t intr = 0x13;
- static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 };
- static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 };
- const uint8_t hid_spec[] = {
- 0x05, 0x01, // usage page
- 0x09, 0x06, // keyboard
- 0xa1, 0x01, // key codes
- 0x85, 0x01, // minimum
- 0x05, 0x07, // max
- 0x19, 0xe0, // logical min
- 0x29, 0xe7, // logical max
- 0x15, 0x00, // report size
- 0x25, 0x01, // report count
- 0x75, 0x01, // input data variable absolute
- 0x95, 0x08, // report count
- 0x81, 0x02, // report size
- 0x75, 0x08,
- 0x95, 0x01,
- 0x81, 0x01,
- 0x75, 0x01,
- 0x95, 0x05,
- 0x05, 0x08,
- 0x19, 0x01,
- 0x29, 0x05,
- 0x91, 0x02,
- 0x75, 0x03,
- 0x95, 0x01,
- 0x91, 0x01,
- 0x75, 0x08,
- 0x95, 0x06,
- 0x15, 0x00,
- 0x26, 0xff,
- 0x00, 0x05,
- 0x07, 0x19,
- 0x00, 0x2a,
- 0xff, 0x00,
- 0x81, 0x00,
- 0x75, 0x01,
- 0x95, 0x01,
- 0x15, 0x00,
- 0x25, 0x01,
- 0x05, 0x0c,
- 0x09, 0xb8,
- 0x81, 0x06,
- 0x09, 0xe2,
- 0x81, 0x06,
- 0x09, 0xe9,
- 0x81, 0x02,
- 0x09, 0xea,
- 0x81, 0x02,
- 0x75, 0x01,
- 0x95, 0x04,
- 0x81, 0x01,
- 0xc0 // end tag
- };
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_add_lang_attr(&record);
- sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &hidkb_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, profile);
- sdp_set_profile_descs(&record, pfseq);
- /* protocols */
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &ctrl);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- /* additional protocols */
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &intr);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_add_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL);
- for (i = 0; i < sizeof(hid_attr) / 2; i++)
- sdp_attr_add_new(&record,
- SDP_ATTR_HID_DEVICE_RELEASE_NUMBER + i,
- SDP_UINT16, &hid_attr[i]);
- dtds[0] = &dtd2;
- values[0] = &hid_spec_type;
- dtds[1] = &dtd_data;
- values[1] = (uint8_t *) hid_spec;
- leng[0] = 0;
- leng[1] = sizeof(hid_spec);
- hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
- hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
- for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
- dtds2[i] = &dtd;
- values2[i] = &hid_attr_lang[i];
- }
- lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
- lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
- sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]);
- for (i = 0; i < sizeof(hid_attr2) / 2 - 1; i++)
- sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP + i,
- SDP_UINT16, &hid_attr2[i + 1]);
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("HID keyboard service registered\n");
- return 0;
- }
- static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[3];
- sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
- unsigned int i;
- uint8_t dtd = SDP_UINT16;
- uint8_t dtd2 = SDP_UINT8;
- uint8_t dtd_data = SDP_TEXT_STR8;
- void *dtds[2];
- void *values[2];
- void *dtds2[2];
- void *values2[2];
- int leng[2];
- uint8_t hid_spec_type = 0x22;
- uint16_t hid_attr_lang[] = { 0x409, 0x100 };
- uint16_t ctrl = 0x11, intr = 0x13;
- uint16_t hid_release = 0x0100, parser_version = 0x0111;
- uint8_t subclass = 0x04, country = 0x33;
- uint8_t virtual_cable = 0, reconnect = 1, sdp_disable = 0;
- uint8_t battery = 1, remote_wakeup = 1;
- uint16_t profile_version = 0x0100, superv_timeout = 0x0c80;
- uint8_t norm_connect = 0, boot_device = 0;
- const uint8_t hid_spec[] = {
- 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10,
- 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
- 0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
- 0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
- 0xc0, 0x00
- };
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &hid_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(NULL, profile);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &ctrl);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- proto[1] = sdp_list_append(0, &l2cap_uuid);
- psm = sdp_data_alloc(SDP_UINT16, &intr);
- proto[1] = sdp_list_append(proto[1], psm);
- apseq = sdp_list_append(0, proto[1]);
- sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
- proto[2] = sdp_list_append(0, &hidp_uuid);
- apseq = sdp_list_append(apseq, proto[2]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_add_access_protos(&record, aproto);
- sdp_add_lang_attr(&record);
- sdp_set_info_attr(&record, "Nintendo RVL-CNT-01",
- "Nintendo", "Nintendo RVL-CNT-01");
- sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
- SDP_UINT16, &hid_release);
- sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION,
- SDP_UINT16, &parser_version);
- sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS,
- SDP_UINT8, &subclass);
- sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE,
- SDP_UINT8, &country);
- sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE,
- SDP_BOOL, &virtual_cable);
- sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE,
- SDP_BOOL, &reconnect);
- dtds[0] = &dtd2;
- values[0] = &hid_spec_type;
- dtds[1] = &dtd_data;
- values[1] = (uint8_t *) hid_spec;
- leng[0] = 0;
- leng[1] = sizeof(hid_spec);
- hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
- hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
- for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
- dtds2[i] = &dtd;
- values2[i] = &hid_attr_lang[i];
- }
- lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
- lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
- sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
- sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE,
- SDP_BOOL, &sdp_disable);
- sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER,
- SDP_BOOL, &battery);
- sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP,
- SDP_BOOL, &remote_wakeup);
- sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION,
- SDP_UINT16, &profile_version);
- sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT,
- SDP_UINT16, &superv_timeout);
- sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE,
- SDP_BOOL, &norm_connect);
- sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE,
- SDP_BOOL, &boot_device);
- if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("Wii-Mote service registered\n");
- return 0;
- }
- static int add_cip(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, cmtp, cip;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t psm = si->psm ? si->psm : 0x1001;
- uint8_t netid = si->network ? si->network : 0x02; // 0x02 = ISDN, 0x03 = GSM
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&cip, CIP_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &cip);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, CIP_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
- proto[0] = sdp_list_append(proto[0], sdp_data_alloc(SDP_UINT16, &psm));
- apseq = sdp_list_append(apseq, proto[0]);
- sdp_uuid16_create(&cmtp, CMTP_UUID);
- proto[1] = sdp_list_append(0, &cmtp);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
- sdp_set_info_attr(&record, "Common ISDN Access", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("CIP service registered\n");
- end:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- sdp_data_free(network);
- return ret;
- }
- static int add_ctp(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, tcsbin, ctp;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint8_t netid = si->network ? si->network : 0x02; // 0x01-0x07 cf. p120 profile document
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&ctp, CORDLESS_TELEPHONY_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &ctp);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, CORDLESS_TELEPHONY_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&tcsbin, TCS_BIN_UUID);
- proto[1] = sdp_list_append(0, &tcsbin);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
- sdp_set_info_attr(&record, "Cordless Telephony", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto end;
- }
- printf("CTP service registered\n");
- end:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- sdp_data_free(network);
- return ret;
- }
- static int add_a2source(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avdtp, a2src;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version;
- uint16_t lp = 0x0019, ver = 0x0100;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &a2src);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&avdtp, AVDTP_UUID);
- proto[1] = sdp_list_append(0, &avdtp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Audio Source", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
- printf("Audio source service registered\n");
- done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_a2sink(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avdtp, a2snk;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version;
- uint16_t lp = 0x0019, ver = 0x0100;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&a2snk, AUDIO_SINK_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &a2snk);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&avdtp, AVDTP_UUID);
- proto[1] = sdp_list_append(0, &avdtp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Audio Sink", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
- printf("Audio sink service registered\n");
- done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_avrct(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avctp, avrct;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version, *features;
- uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &avrct);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&avctp, AVCTP_UUID);
- proto[1] = sdp_list_append(0, &avctp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- features = sdp_data_alloc(SDP_UINT16, &feat);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
- sdp_set_info_attr(&record, "AVRCP CT", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
- printf("Remote control service registered\n");
- done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_avrtg(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, l2cap, avctp, avrtg;
- sdp_profile_desc_t profile[1];
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *psm, *version, *features;
- uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
- int ret = 0;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &avrtg);
- sdp_set_service_classes(&record, svclass_id);
- sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
- profile[0].version = 0x0100;
- pfseq = sdp_list_append(0, &profile[0]);
- sdp_set_profile_descs(&record, pfseq);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &lp);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(0, proto[0]);
- sdp_uuid16_create(&avctp, AVCTP_UUID);
- proto[1] = sdp_list_append(0, &avctp);
- version = sdp_data_alloc(SDP_UINT16, &ver);
- proto[1] = sdp_list_append(proto[1], version);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
- features = sdp_data_alloc(SDP_UINT16, &feat);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
- sdp_set_info_attr(&record, "AVRCP TG", 0, 0);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- ret = -1;
- goto done;
- }
- printf("Remote target service registered\n");
- done:
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto, 0);
- return ret;
- }
- static int add_udi_ue(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 18;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_uuid16_create(&svclass_uuid, UDI_MT_SVCLASS_ID);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_list_free(svclass, NULL);
- sdp_set_info_attr(&record, "UDI UE", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("UDI UE service registered\n");
- return 0;
- }
- static int add_udi_te(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 19;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_uuid16_create(&svclass_uuid, UDI_TA_SVCLASS_ID);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_list_free(svclass, NULL);
- sdp_set_info_attr(&record, "UDI TE", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("UDI TE service registered\n");
- return 0;
- }
- static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0,
- 0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 };
- static int add_sr1(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass;
- uuid_t root_uuid, svclass_uuid;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("Toshiba Speech Recognition SR-1 service record registered\n");
- return 0;
- }
- static unsigned char syncmls_uuid[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
- static unsigned char syncmlc_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
- static int add_syncml(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
- uint8_t channel = si->channel ? si->channel: 15;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
- sdp_uuid16_create(&obex_uuid, OBEX_UUID);
- proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_set_info_attr(&record, "SyncML Client", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("SyncML Client service record registered\n");
- return 0;
- }
- static unsigned char async_uuid[] = { 0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62,
- 0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C };
- static int add_activesync(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 21;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_uuid128_create(&svclass_uuid, (void *) async_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("ActiveSync service record registered\n");
- return 0;
- }
- static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
- 0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
- static int add_hotsync(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 22;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("HotSync service record registered\n");
- return 0;
- }
- static unsigned char palmos_uuid[] = { 0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51,
- 0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 };
- static int add_palmos(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass;
- uuid_t root_uuid, svclass_uuid;
- int err;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- err = sdp_device_record_register(session, &interface, &record,
- SDP_RECORD_PERSIST);
- sdp_list_free(root, NULL);
- sdp_list_free(svclass, NULL);
- if (err < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("PalmOS service record registered\n");
- return 0;
- }
- static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
- static int add_nokiaid(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass;
- uuid_t root_uuid, svclass_uuid;
- uint16_t verid = 0x005f;
- sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid);
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- sdp_data_free(version);
- return -1;
- }
- printf("Nokia ID service record registered\n");
- return 0;
- }
- static unsigned char pcsuite_uuid[] = { 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
- static int add_pcsuite(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel: 14;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid);
- svclass = sdp_list_append(NULL, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("Nokia PC Suite service registered\n");
- return 0;
- }
- static unsigned char nftp_uuid[] = { 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
- static unsigned char nsyncml_uuid[] = { 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
- static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
- static unsigned char apple_uuid[] = { 0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90,
- 0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 };
- static unsigned char iap_uuid[] = { 0x00, 0x00, 0x00, 0x00, 0xde, 0xca, 0xfa, 0xde,
- 0xde, 0xca, 0xde, 0xaf, 0xde, 0xca, 0xca, 0xfe };
- static int add_apple(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root;
- uuid_t root_uuid;
- uint32_t attr783 = 0x00000000;
- uint32_t attr785 = 0x00000002;
- uint16_t attr786 = 0x1234;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_attr_add_new(&record, 0x0780, SDP_UUID128, (void *) apple_uuid);
- sdp_attr_add_new(&record, 0x0781, SDP_TEXT_STR8, (void *) "Macmini");
- sdp_attr_add_new(&record, 0x0782, SDP_TEXT_STR8, (void *) "PowerMac10,1");
- sdp_attr_add_new(&record, 0x0783, SDP_UINT32, (void *) &attr783);
- sdp_attr_add_new(&record, 0x0784, SDP_TEXT_STR8, (void *) "1.6.6f22");
- sdp_attr_add_new(&record, 0x0785, SDP_UINT32, (void *) &attr785);
- sdp_attr_add_new(&record, 0x0786, SDP_UUID16, (void *) &attr786);
- sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("Apple attribute service registered\n");
- return 0;
- }
- static int add_isync(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_list_t *root, *svclass, *proto;
- uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid;
- uint8_t channel = si->channel ? si->channel : 16;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto = sdp_list_append(proto, sdp_list_append(
- sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID);
- svclass = sdp_list_append(NULL, &serial_uuid);
- sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID);
- svclass = sdp_list_append(svclass, &svclass_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd.");
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- printf("Apple iSync service registered\n");
- return 0;
- }
- static int add_semchla(sdp_session_t *session, svc_info_t *si)
- {
- sdp_record_t record;
- sdp_profile_desc_t profile;
- sdp_list_t *root, *svclass, *proto, *profiles;
- uuid_t root_uuid, service_uuid, l2cap_uuid, semchla_uuid;
- uint16_t psm = 0xf0f9;
- memset(&record, 0, sizeof(record));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto = sdp_list_append(NULL, sdp_list_append(
- sdp_list_append(NULL, &l2cap_uuid), sdp_data_alloc(SDP_UINT16, &psm)));
- sdp_uuid32_create(&semchla_uuid, 0x8e770300);
- proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid));
- sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
- sdp_uuid32_create(&service_uuid, 0x8e771301);
- svclass = sdp_list_append(NULL, &service_uuid);
- sdp_set_service_classes(&record, svclass);
- sdp_uuid32_create(&profile.uuid, 0x8e771302); // Headset
- //sdp_uuid32_create(&profile.uuid, 0x8e771303); // Phone
- profile.version = 0x0100;
- profiles = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(&record, profiles);
- sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL);
- if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
- printf("Service Record registration failed\n");
- return -1;
- }
- /* SEMC High Level Authentication */
- printf("SEMC HLA service registered\n");
- return 0;
- }
- static int add_gatt(sdp_session_t *session, svc_info_t *si)
- {
- sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
- uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap;
- sdp_profile_desc_t profile;
- sdp_record_t record;
- sdp_data_t *psm, *sh, *eh;
- uint16_t att_psm = 27, start = 0x0001, end = 0x000f;
- int ret;
- memset(&record, 0, sizeof(sdp_record_t));
- record.handle = si->handle;
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(&record, root);
- sdp_list_free(root, NULL);
- sdp_uuid16_create(&gatt_uuid, GENERIC_ATTRIB_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &gatt_uuid);
- sdp_set_service_classes(&record, svclass_id);
- sdp_list_free(svclass_id, NULL);
- sdp_uuid16_create(&profile.uuid, GENERIC_ATTRIB_PROFILE_ID);
- profile.version = 0x0100;
- profiles = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(&record, profiles);
- sdp_list_free(profiles, NULL);
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(NULL, &l2cap);
- psm = sdp_data_alloc(SDP_UINT16, &att_psm);
- proto[0] = sdp_list_append(proto[0], psm);
- apseq = sdp_list_append(NULL, proto[0]);
- sdp_uuid16_create(&proto_uuid, ATT_UUID);
- proto[1] = sdp_list_append(NULL, &proto_uuid);
- sh = sdp_data_alloc(SDP_UINT16, &start);
- proto[1] = sdp_list_append(proto[1], sh);
- eh = sdp_data_alloc(SDP_UINT16, &end);
- proto[1] = sdp_list_append(proto[1], eh);
- apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(NULL, apseq);
- sdp_set_access_protos(&record, aproto);
- sdp_set_info_attr(&record, "Generic Attribute Profile", "BlueZ", NULL);
- sdp_set_url_attr(&record, "http://www.bluez.org/",
- "http://www.bluez.org/", "http://www.bluez.org/");
- sdp_set_service_id(&record, gatt_uuid);
- ret = sdp_device_record_register(session, &interface, &record,
- SDP_RECORD_PERSIST);
- if (ret < 0)
- printf("Service Record registration failed\n");
- else
- printf("Generic Attribute Profile Service registered\n");
- sdp_data_free(psm);
- sdp_data_free(sh);
- sdp_data_free(eh);
- sdp_list_free(proto[0], NULL);
- sdp_list_free(proto[1], NULL);
- sdp_list_free(apseq, NULL);
- sdp_list_free(aproto, NULL);
- return ret;
- }
- struct {
- char *name;
- uint32_t class;
- int (*add)(sdp_session_t *sess, svc_info_t *si);
- unsigned char *uuid;
- } service[] = {
- { "DID", PNP_INFO_SVCLASS_ID, NULL, },
- { "SP", SERIAL_PORT_SVCLASS_ID, add_sp },
- { "DUN", DIALUP_NET_SVCLASS_ID, add_dun },
- { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan },
- { "FAX", FAX_SVCLASS_ID, add_fax },
- { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush },
- { "FTP", OBEX_FILETRANS_SVCLASS_ID, add_ftp },
- { "PRINT", DIRECT_PRINTING_SVCLASS_ID, add_directprint },
- { "HS", HEADSET_SVCLASS_ID, add_headset },
- { "HSAG", HEADSET_AGW_SVCLASS_ID, add_headset_ag },
- { "HF", HANDSFREE_SVCLASS_ID, add_handsfree },
- { "HFAG", HANDSFREE_AGW_SVCLASS_ID, add_handsfree_ag},
- { "SAP", SAP_SVCLASS_ID, add_simaccess },
- { "PBAP", PBAP_SVCLASS_ID, add_pbap, },
- { "MAP", MAP_SVCLASS_ID, add_map, },
- { "NAP", NAP_SVCLASS_ID, add_nap },
- { "GN", GN_SVCLASS_ID, add_gn },
- { "PANU", PANU_SVCLASS_ID, add_panu },
- { "HCRP", HCR_SVCLASS_ID, NULL },
- { "HID", HID_SVCLASS_ID, NULL },
- { "KEYB", HID_SVCLASS_ID, add_hid_keyb },
- { "WIIMOTE", HID_SVCLASS_ID, add_hid_wiimote },
- { "CIP", CIP_SVCLASS_ID, add_cip },
- { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp },
- { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source },
- { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink },
- { "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct },
- { "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg },
- { "UDIUE", UDI_MT_SVCLASS_ID, add_udi_ue },
- { "UDITE", UDI_TA_SVCLASS_ID, add_udi_te },
- { "SEMCHLA", 0x8e771301, add_semchla },
- { "SR1", 0, add_sr1, sr1_uuid },
- { "SYNCML", 0, add_syncml, syncmlc_uuid },
- { "SYNCMLSERV", 0, NULL, syncmls_uuid },
- { "ACTIVESYNC", 0, add_activesync, async_uuid },
- { "HOTSYNC", 0, add_hotsync, hotsync_uuid },
- { "PALMOS", 0, add_palmos, palmos_uuid },
- { "NOKID", 0, add_nokiaid, nokid_uuid },
- { "PCSUITE", 0, add_pcsuite, pcsuite_uuid },
- { "NFTP", 0, NULL, nftp_uuid },
- { "NSYNCML", 0, NULL, nsyncml_uuid },
- { "NGAGE", 0, NULL, ngage_uuid },
- { "APPLE", 0, add_apple, apple_uuid },
- { "IAP", 0, NULL, iap_uuid },
- { "ISYNC", APPLE_AGENT_SVCLASS_ID, add_isync, },
- { "GATT", GENERIC_ATTRIB_SVCLASS_ID, add_gatt, },
- { 0 }
- };
- /* Add local service */
- static int add_service(bdaddr_t *bdaddr, svc_info_t *si)
- {
- sdp_session_t *sess;
- int i, ret = -1;
- if (!si->name)
- return -1;
- sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
- if (!sess)
- return -1;
- for (i = 0; service[i].name; i++)
- if (!strcasecmp(service[i].name, si->name)) {
- if (service[i].add)
- ret = service[i].add(sess, si);
- goto done;
- }
- printf("Unknown service name: %s\n", si->name);
- done:
- free(si->name);
- sdp_close(sess);
- return ret;
- }
- static struct option add_options[] = {
- { "help", 0, 0, 'h' },
- { "handle", 1, 0, 'r' },
- { "psm", 1, 0, 'p' },
- { "channel", 1, 0, 'c' },
- { "network", 1, 0, 'n' },
- { 0, 0, 0, 0 }
- };
- static const char *add_help =
- "Usage:\n"
- "\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n";
- static int cmd_add(int argc, char **argv)
- {
- svc_info_t si;
- int opt;
- memset(&si, 0, sizeof(si));
- si.handle = 0xffffffff;
- for_each_opt(opt, add_options, 0) {
- switch (opt) {
- case 'r':
- if (strncasecmp(optarg, "0x", 2))
- si.handle = atoi(optarg);
- else
- si.handle = strtol(optarg + 2, NULL, 16);
- break;
- case 'p':
- if (strncasecmp(optarg, "0x", 2))
- si.psm = atoi(optarg);
- else
- si.psm = strtol(optarg + 2, NULL, 16);
- break;
- case 'c':
- if (strncasecmp(optarg, "0x", 2))
- si.channel = atoi(optarg);
- else
- si.channel = strtol(optarg + 2, NULL, 16);
- break;
- case 'n':
- if (strncasecmp(optarg, "0x", 2))
- si.network = atoi(optarg);
- else
- si.network = strtol(optarg + 2, NULL, 16);
- break;
- default:
- printf("%s", add_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 1) {
- printf("%s", add_help);
- return -1;
- }
- si.name = strdup(argv[0]);
- return add_service(0, &si);
- }
- /* Delete local service */
- static int del_service(bdaddr_t *bdaddr, void *arg)
- {
- uint32_t handle, range = 0x0000ffff;
- sdp_list_t *attr;
- sdp_session_t *sess;
- sdp_record_t *rec;
- if (!arg) {
- printf("Record handle was not specified.\n");
- return -1;
- }
- sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
- if (!sess) {
- printf("No local SDP server!\n");
- return -1;
- }
- handle = strtoul((char *)arg, 0, 16);
- attr = sdp_list_append(0, &range);
- rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
- sdp_list_free(attr, 0);
- if (!rec) {
- printf("Service Record not found.\n");
- sdp_close(sess);
- return -1;
- }
- if (sdp_device_record_unregister(sess, &interface, rec)) {
- printf("Failed to unregister service record: %s\n", strerror(errno));
- sdp_close(sess);
- return -1;
- }
- printf("Service Record deleted.\n");
- sdp_close(sess);
- return 0;
- }
- static struct option del_options[] = {
- { "help", 0, 0, 'h' },
- { 0, 0, 0, 0 }
- };
- static const char *del_help =
- "Usage:\n"
- "\tdel record_handle\n";
- static int cmd_del(int argc, char **argv)
- {
- int opt;
- for_each_opt(opt, del_options, 0) {
- switch (opt) {
- default:
- printf("%s", del_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 1) {
- printf("%s", del_help);
- return -1;
- }
- return del_service(NULL, argv[0]);
- }
- /*
- * Perform an inquiry and search/browse all peer found.
- */
- static void inquiry(handler_t handler, void *arg)
- {
- inquiry_info ii[20];
- uint8_t count = 0;
- int i;
- printf("Inquiring ...\n");
- if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
- printf("Inquiry failed\n");
- return;
- }
- for (i = 0; i < count; i++)
- handler(&ii[i].bdaddr, arg);
- }
- static void doprintf(void *data, const char *str)
- {
- printf("%s", str);
- }
- /*
- * Search for a specific SDP service
- */
- static int do_search(bdaddr_t *bdaddr, struct search_context *context)
- {
- sdp_list_t *attrid, *search, *seq, *next;
- uint32_t range = 0x0000ffff;
- char str[20];
- sdp_session_t *sess;
- if (!bdaddr) {
- inquiry(do_search, context);
- return 0;
- }
- sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
- ba2str(bdaddr, str);
- if (!sess) {
- printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
- return -1;
- }
- if (context->view != RAW_VIEW) {
- if (context->svc)
- printf("Searching for %s on %s ...\n", context->svc, str);
- else
- printf("Browsing %s ...\n", str);
- }
- attrid = sdp_list_append(0, &range);
- search = sdp_list_append(0, &context->group);
- if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) {
- printf("Service Search failed: %s\n", strerror(errno));
- sdp_list_free(attrid, 0);
- sdp_list_free(search, 0);
- sdp_close(sess);
- return -1;
- }
- sdp_list_free(attrid, 0);
- sdp_list_free(search, 0);
- for (; seq; seq = next) {
- sdp_record_t *rec = (sdp_record_t *) seq->data;
- struct search_context sub_context;
- switch (context->view) {
- case DEFAULT_VIEW:
- /* Display user friendly form */
- print_service_attr(rec);
- printf("\n");
- break;
- case TREE_VIEW:
- /* Display full tree */
- print_tree_attr(rec);
- printf("\n");
- break;
- case XML_VIEW:
- /* Display raw XML tree */
- convert_sdp_record_to_xml(rec, 0, doprintf);
- break;
- default:
- /* Display raw tree */
- print_raw_attr(rec);
- break;
- }
- /* Set the subcontext for browsing the sub tree */
- memcpy(&sub_context, context, sizeof(struct search_context));
- if (sdp_get_group_id(rec, &sub_context.group) != -1) {
- /* Browse the next level down if not done */
- if (sub_context.group.value.uuid16 != context->group.value.uuid16)
- do_search(bdaddr, &sub_context);
- }
- next = seq->next;
- free(seq);
- sdp_record_free(rec);
- }
- sdp_close(sess);
- return 0;
- }
- static struct option browse_options[] = {
- { "help", 0, 0, 'h' },
- { "tree", 0, 0, 't' },
- { "raw", 0, 0, 'r' },
- { "xml", 0, 0, 'x' },
- { "uuid", 1, 0, 'u' },
- { "l2cap", 0, 0, 'l' },
- { 0, 0, 0, 0 }
- };
- static const char *browse_help =
- "Usage:\n"
- "\tbrowse [--tree] [--raw] [--xml] [--uuid uuid] [--l2cap] [bdaddr]\n";
- /*
- * Browse the full SDP database (i.e. list all services starting from the
- * root/top-level).
- */
- static int cmd_browse(int argc, char **argv)
- {
- struct search_context context;
- int opt, num;
- /* Initialise context */
- memset(&context, '\0', sizeof(struct search_context));
- /* We want to browse the top-level/root */
- sdp_uuid16_create(&context.group, PUBLIC_BROWSE_GROUP);
- for_each_opt(opt, browse_options, 0) {
- switch (opt) {
- case 't':
- context.view = TREE_VIEW;
- break;
- case 'r':
- context.view = RAW_VIEW;
- break;
- case 'x':
- context.view = XML_VIEW;
- break;
- case 'u':
- if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) {
- printf("Invalid uuid %s\n", optarg);
- return -1;
- }
- sdp_uuid16_create(&context.group, num);
- break;
- case 'l':
- sdp_uuid16_create(&context.group, L2CAP_UUID);
- break;
- default:
- printf("%s", browse_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc >= 1) {
- bdaddr_t bdaddr;
- estr2ba(argv[0], &bdaddr);
- return do_search(&bdaddr, &context);
- }
- return do_search(NULL, &context);
- }
- static struct option search_options[] = {
- { "help", 0, 0, 'h' },
- { "bdaddr", 1, 0, 'b' },
- { "tree", 0, 0, 't' },
- { "raw", 0, 0, 'r' },
- { "xml", 0, 0, 'x' },
- { 0, 0, 0, 0}
- };
- static const char *search_help =
- "Usage:\n"
- "\tsearch [--bdaddr bdaddr] [--tree] [--raw] [--xml] SERVICE\n"
- "SERVICE is a name (string) or UUID (0x1002)\n";
- /*
- * Search for a specific SDP service
- *
- * Note : we should support multiple services on the command line :
- * sdptool search 0x0100 0x000f 0x1002
- * (this would search a service supporting both L2CAP and BNEP directly in
- * the top level browse group)
- */
- static int cmd_search(int argc, char **argv)
- {
- struct search_context context;
- unsigned char *uuid = NULL;
- uint32_t class = 0;
- bdaddr_t bdaddr;
- int has_addr = 0;
- int i;
- int opt;
- /* Initialise context */
- memset(&context, '\0', sizeof(struct search_context));
- for_each_opt(opt, search_options, 0) {
- switch (opt) {
- case 'b':
- estr2ba(optarg, &bdaddr);
- has_addr = 1;
- break;
- case 't':
- context.view = TREE_VIEW;
- break;
- case 'r':
- context.view = RAW_VIEW;
- break;
- case 'x':
- context.view = XML_VIEW;
- break;
- default:
- printf("%s", search_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 1) {
- printf("%s", search_help);
- return -1;
- }
- /* Note : we need to find a way to support search combining
- * multiple services */
- context.svc = strdup(argv[0]);
- if (!strncasecmp(context.svc, "0x", 2)) {
- int num;
- /* This is a UUID16, just convert to int */
- sscanf(context.svc + 2, "%X", &num);
- class = num;
- printf("Class 0x%X\n", class);
- } else {
- /* Convert class name to an UUID */
- for (i = 0; service[i].name; i++)
- if (strcasecmp(context.svc, service[i].name) == 0) {
- class = service[i].class;
- uuid = service[i].uuid;
- break;
- }
- if (!class && !uuid) {
- printf("Unknown service %s\n", context.svc);
- return -1;
- }
- }
- if (class) {
- if (class & 0xffff0000)
- sdp_uuid32_create(&context.group, class);
- else {
- uint16_t class16 = class & 0xffff;
- sdp_uuid16_create(&context.group, class16);
- }
- } else
- sdp_uuid128_create(&context.group, uuid);
- if (has_addr)
- return do_search(&bdaddr, &context);
- return do_search(NULL, &context);
- }
- /*
- * Show how to get a specific SDP record by its handle.
- * Not really useful to the user, just show how it can be done...
- */
- static int get_service(bdaddr_t *bdaddr, struct search_context *context, int quite)
- {
- sdp_list_t *attrid;
- uint32_t range = 0x0000ffff;
- sdp_record_t *rec;
- sdp_session_t *session = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
- if (!session) {
- char str[20];
- ba2str(bdaddr, str);
- printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
- return -1;
- }
- attrid = sdp_list_append(0, &range);
- rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid);
- sdp_list_free(attrid, 0);
- sdp_close(session);
- if (!rec) {
- if (!quite) {
- printf("Service get request failed.\n");
- return -1;
- } else
- return 0;
- }
- switch (context->view) {
- case DEFAULT_VIEW:
- /* Display user friendly form */
- print_service_attr(rec);
- printf("\n");
- break;
- case TREE_VIEW:
- /* Display full tree */
- print_tree_attr(rec);
- printf("\n");
- break;
- case XML_VIEW:
- /* Display raw XML tree */
- convert_sdp_record_to_xml(rec, 0, doprintf);
- break;
- default:
- /* Display raw tree */
- print_raw_attr(rec);
- break;
- }
- sdp_record_free(rec);
- return 0;
- }
- static struct option records_options[] = {
- { "help", 0, 0, 'h' },
- { "tree", 0, 0, 't' },
- { "raw", 0, 0, 'r' },
- { "xml", 0, 0, 'x' },
- { 0, 0, 0, 0 }
- };
- static const char *records_help =
- "Usage:\n"
- "\trecords [--tree] [--raw] [--xml] bdaddr\n";
- /*
- * Request possible SDP service records
- */
- static int cmd_records(int argc, char **argv)
- {
- struct search_context context;
- uint32_t base[] = { 0x10000, 0x10300, 0x10500,
- 0x1002e, 0x110b, 0x90000, 0x2008000,
- 0x4000000, 0x100000, 0x1000000,
- 0x4f491100, 0x4f491200 };
- bdaddr_t bdaddr;
- unsigned int i, n, num = 32;
- int opt, err = 0;
- /* Initialise context */
- memset(&context, '\0', sizeof(struct search_context));
- for_each_opt(opt, records_options, 0) {
- switch (opt) {
- case 't':
- context.view = TREE_VIEW;
- break;
- case 'r':
- context.view = RAW_VIEW;
- break;
- case 'x':
- context.view = XML_VIEW;
- break;
- default:
- printf("%s", records_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 1) {
- printf("%s", records_help);
- return -1;
- }
- /* Convert command line parameters */
- estr2ba(argv[0], &bdaddr);
- for (i = 0; i < sizeof(base) / sizeof(uint32_t); i++)
- for (n = 0; n < num; n++) {
- context.handle = base[i] + n;
- err = get_service(&bdaddr, &context, 1);
- if (err < 0)
- return 0;
- }
- return 0;
- }
- static struct option get_options[] = {
- { "help", 0, 0, 'h' },
- { "bdaddr", 1, 0, 'b' },
- { "tree", 0, 0, 't' },
- { "raw", 0, 0, 'r' },
- { "xml", 0, 0, 'x' },
- { 0, 0, 0, 0 }
- };
- static const char *get_help =
- "Usage:\n"
- "\tget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\n";
- /*
- * Get a specific SDP record on the local SDP server
- */
- static int cmd_get(int argc, char **argv)
- {
- struct search_context context;
- bdaddr_t bdaddr;
- int has_addr = 0;
- int opt;
- /* Initialise context */
- memset(&context, '\0', sizeof(struct search_context));
- for_each_opt(opt, get_options, 0) {
- switch (opt) {
- case 'b':
- estr2ba(optarg, &bdaddr);
- has_addr = 1;
- break;
- case 't':
- context.view = TREE_VIEW;
- break;
- case 'r':
- context.view = RAW_VIEW;
- break;
- case 'x':
- context.view = XML_VIEW;
- break;
- default:
- printf("%s", get_help);
- return -1;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 1) {
- printf("%s", get_help);
- return -1;
- }
- /* Convert command line parameters */
- context.handle = strtoul(argv[0], 0, 16);
- return get_service(has_addr ? &bdaddr : BDADDR_LOCAL, &context, 0);
- }
- static struct {
- char *cmd;
- int (*func)(int argc, char **argv);
- char *doc;
- } command[] = {
- { "search", cmd_search, "Search for a service" },
- { "browse", cmd_browse, "Browse all available services" },
- { "records", cmd_records, "Request all records" },
- { "add", cmd_add, "Add local service" },
- { "del", cmd_del, "Delete local service" },
- { "get", cmd_get, "Get local service" },
- { "setattr", cmd_setattr, "Set/Add attribute to a SDP record" },
- { "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" },
- { 0, 0, 0 }
- };
- static void usage(void)
- {
- int i, pos = 0;
- printf("sdptool - SDP tool v%s\n", VERSION);
- printf("Usage:\n"
- "\tsdptool [options] <command> [command parameters]\n");
- printf("Options:\n"
- "\t-h\t\tDisplay help\n"
- "\t-i\t\tSpecify source interface\n");
- printf("Commands:\n");
- for (i = 0; command[i].cmd; i++)
- printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc);
- printf("\nServices:\n\t");
- for (i = 0; service[i].name; i++) {
- printf("%s ", service[i].name);
- pos += strlen(service[i].name) + 1;
- if (pos > 60) {
- printf("\n\t");
- pos = 0;
- }
- }
- printf("\n");
- }
- static struct option main_options[] = {
- { "help", 0, 0, 'h' },
- { "device", 1, 0, 'i' },
- { 0, 0, 0, 0 }
- };
- int main(int argc, char *argv[])
- {
- int i, opt;
- bacpy(&interface, BDADDR_ANY);
- while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
- switch(opt) {
- case 'i':
- if (!strncmp(optarg, "hci", 3))
- hci_devba(atoi(optarg + 3), &interface);
- else
- str2ba(optarg, &interface);
- break;
- case 'h':
- usage();
- exit(0);
- default:
- exit(1);
- }
- }
- argc -= optind;
- argv += optind;
- optind = 0;
- if (argc < 1) {
- usage();
- exit(1);
- }
- for (i = 0; command[i].cmd; i++)
- if (strncmp(command[i].cmd, argv[0], 4) == 0)
- return command[i].func(argc, argv);
- return 1;
- }
|