1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2001-2002 Nokia Corporation 6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk (at) qualcomm.com> 7 * Copyright (C) 2002-2009 Marcel Holtmann <marcel (at) holtmann.org> 8 * Copyright (C) 2002-2003 Stephen Crane <steve.crane (at) rococosoft.com> 9 * Copyright (C) 2002-2003 Jean Tourrilhes <jt (at) hpl.hp.com> 10 * 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 * 26 */ 27 28 #ifdef HAVE_CONFIG_H 29 #include <config.h> 30 #endif 31 32 #include <stdio.h> 33 #include <errno.h> 34 #include <ctype.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <getopt.h> 38 #include <sys/socket.h> 39 40 #include <bluetooth/bluetooth.h> 41 #include <bluetooth/hci.h> 42 #include <bluetooth/hci_lib.h> 43 #include <bluetooth/sdp.h> 44 #include <bluetooth/sdp_lib.h> 45 46 #include <netinet/in.h> 47 48 #include "sdp-xml.h" 49 50 #ifndef APPLE_AGENT_SVCLASS_ID 51 #define APPLE_AGENT_SVCLASS_ID 0x2112 52 #endif 53 54 #define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1) 55 56 /* 57 * Convert a string to a BDADDR, with a few "enhancements" - Jean II 58 */ 59 static int estr2ba(char *str, bdaddr_t *ba) 60 { 61 /* Only trap "local", "any" is already dealt with */ 62 if(!strcmp(str, "local")) { 63 bacpy(ba, BDADDR_LOCAL); 64 return 0; 65 } 66 return str2ba(str, ba); 67 } 68 69 #define DEFAULT_VIEW 0 /* Display only known attribute */ 70 #define TREE_VIEW 1 /* Display full attribute tree */ 71 #define RAW_VIEW 2 /* Display raw tree */ 72 #define XML_VIEW 3 /* Display xml tree */ 73 74 /* Pass args to the inquiry/search handler */ 75 struct search_context { 76 char *svc; /* Service */ 77 uuid_t group; /* Browse group */ 78 int view; /* View mode */ 79 uint32_t handle; /* Service record handle */ 80 }; 81 82 typedef int (*handler_t)(bdaddr_t *bdaddr, struct search_context *arg); 83 84 static char UUID_str[MAX_LEN_UUID_STR]; 85 static bdaddr_t interface; 86 87 /* Definition of attribute members */ 88 struct member_def { 89 char *name; 90 }; 91 92 /* Definition of an attribute */ 93 struct attrib_def { 94 int num; /* Numeric ID - 16 bits */ 95 char *name; /* User readable name */ 96 struct member_def *members; /* Definition of attribute args */ 97 int member_max; /* Max of attribute arg definitions */ 98 }; 99 100 /* Definition of a service or protocol */ 101 struct uuid_def { 102 int num; /* Numeric ID - 16 bits */ 103 char *name; /* User readable name */ 104 struct attrib_def *attribs; /* Specific attribute definitions */ 105 int attrib_max; /* Max of attribute definitions */ 106 }; 107 108 /* Context information about current attribute */ 109 struct attrib_context { 110 struct uuid_def *service; /* Service UUID, if known */ 111 struct attrib_def *attrib; /* Description of the attribute */ 112 int member_index; /* Index of current attribute member */ 113 }; 114 115 /* Context information about the whole service */ 116 struct service_context { 117 struct uuid_def *service; /* Service UUID, if known */ 118 }; 119 120 /* Allow us to do nice formatting of the lists */ 121 static char *indent_spaces = " "; 122 123 /* ID of the service attribute. 124 * Most attributes after 0x200 are defined based on the service, so 125 * we need to find what is the service (which is messy) - Jean II */ 126 #define SERVICE_ATTR 0x1 127 128 /* Definition of the optional arguments in protocol list */ 129 static struct member_def protocol_members[] = { 130 { "Protocol" }, 131 { "Channel/Port" }, 132 { "Version" }, 133 }; 134 135 /* Definition of the optional arguments in profile list */ 136 static struct member_def profile_members[] = { 137 { "Profile" }, 138 { "Version" }, 139 }; 140 141 /* Definition of the optional arguments in Language list */ 142 static struct member_def language_members[] = { 143 { "Code ISO639" }, 144 { "Encoding" }, 145 { "Base Offset" }, 146 }; 147 148 /* Name of the various common attributes. See BT assigned numbers */ 149 static struct attrib_def attrib_names[] = { 150 { 0x0, "ServiceRecordHandle", NULL, 0 }, 151 { 0x1, "ServiceClassIDList", NULL, 0 }, 152 { 0x2, "ServiceRecordState", NULL, 0 }, 153 { 0x3, "ServiceID", NULL, 0 }, 154 { 0x4, "ProtocolDescriptorList", 155 protocol_members, sizeof(protocol_members)/sizeof(struct member_def) }, 156 { 0x5, "BrowseGroupList", NULL, 0 }, 157 { 0x6, "LanguageBaseAttributeIDList", 158 language_members, sizeof(language_members)/sizeof(struct member_def) }, 159 { 0x7, "ServiceInfoTimeToLive", NULL, 0 }, 160 { 0x8, "ServiceAvailability", NULL, 0 }, 161 { 0x9, "BluetoothProfileDescriptorList", 162 profile_members, sizeof(profile_members)/sizeof(struct member_def) }, 163 { 0xA, "DocumentationURL", NULL, 0 }, 164 { 0xB, "ClientExecutableURL", NULL, 0 }, 165 { 0xC, "IconURL", NULL, 0 }, 166 { 0xD, "AdditionalProtocolDescriptorLists", NULL, 0 }, 167 /* Definitions after that are tricky (per profile or offset) */ 168 }; 169 170 const int attrib_max = sizeof(attrib_names)/sizeof(struct attrib_def); 171 172 /* Name of the various SPD attributes. See BT assigned numbers */ 173 static struct attrib_def sdp_attrib_names[] = { 174 { 0x200, "VersionNumberList", NULL, 0 }, 175 { 0x201, "ServiceDatabaseState", NULL, 0 }, 176 }; 177 178 /* Name of the various SPD attributes. See BT assigned numbers */ 179 static struct attrib_def browse_attrib_names[] = { 180 { 0x200, "GroupID", NULL, 0 }, 181 }; 182 183 /* Name of the various Device ID attributes. See Device Id spec. */ 184 static struct attrib_def did_attrib_names[] = { 185 { 0x200, "SpecificationID", NULL, 0 }, 186 { 0x201, "VendorID", NULL, 0 }, 187 { 0x202, "ProductID", NULL, 0 }, 188 { 0x203, "Version", NULL, 0 }, 189 { 0x204, "PrimaryRecord", NULL, 0 }, 190 { 0x205, "VendorIDSource", NULL, 0 }, 191 }; 192 193 /* Name of the various HID attributes. See HID spec. */ 194 static struct attrib_def hid_attrib_names[] = { 195 { 0x200, "DeviceReleaseNum", NULL, 0 }, 196 { 0x201, "ParserVersion", NULL, 0 }, 197 { 0x202, "DeviceSubclass", NULL, 0 }, 198 { 0x203, "CountryCode", NULL, 0 }, 199 { 0x204, "VirtualCable", NULL, 0 }, 200 { 0x205, "ReconnectInitiate", NULL, 0 }, 201 { 0x206, "DescriptorList", NULL, 0 }, 202 { 0x207, "LangIDBaseList", NULL, 0 }, 203 { 0x208, "SDPDisable", NULL, 0 }, 204 { 0x209, "BatteryPower", NULL, 0 }, 205 { 0x20a, "RemoteWakeup", NULL, 0 }, 206 { 0x20b, "ProfileVersion", NULL, 0 }, 207 { 0x20c, "SupervisionTimeout", NULL, 0 }, 208 { 0x20d, "NormallyConnectable", NULL, 0 }, 209 { 0x20e, "BootDevice", NULL, 0 }, 210 }; 211 212 /* Name of the various PAN attributes. See BT assigned numbers */ 213 /* Note : those need to be double checked - Jean II */ 214 static struct attrib_def pan_attrib_names[] = { 215 { 0x200, "IpSubnet", NULL, 0 }, /* Obsolete ??? */ 216 { 0x30A, "SecurityDescription", NULL, 0 }, 217 { 0x30B, "NetAccessType", NULL, 0 }, 218 { 0x30C, "MaxNetAccessrate", NULL, 0 }, 219 { 0x30D, "IPv4Subnet", NULL, 0 }, 220 { 0x30E, "IPv6Subnet", NULL, 0 }, 221 }; 222 223 /* Name of the various Generic-Audio attributes. See BT assigned numbers */ 224 /* Note : totally untested - Jean II */ 225 static struct attrib_def audio_attrib_names[] = { 226 { 0x302, "Remote audio volume control", NULL, 0 }, 227 }; 228 229 /* Same for the UUIDs. See BT assigned numbers */ 230 static struct uuid_def uuid16_names[] = { 231 /* -- Protocols -- */ 232 { 0x0001, "SDP", NULL, 0 }, 233 { 0x0002, "UDP", NULL, 0 }, 234 { 0x0003, "RFCOMM", NULL, 0 }, 235 { 0x0004, "TCP", NULL, 0 }, 236 { 0x0005, "TCS-BIN", NULL, 0 }, 237 { 0x0006, "TCS-AT", NULL, 0 }, 238 { 0x0008, "OBEX", NULL, 0 }, 239 { 0x0009, "IP", NULL, 0 }, 240 { 0x000a, "FTP", NULL, 0 }, 241 { 0x000c, "HTTP", NULL, 0 }, 242 { 0x000e, "WSP", NULL, 0 }, 243 { 0x000f, "BNEP", NULL, 0 }, 244 { 0x0010, "UPnP/ESDP", NULL, 0 }, 245 { 0x0011, "HIDP", NULL, 0 }, 246 { 0x0012, "HardcopyControlChannel", NULL, 0 }, 247 { 0x0014, "HardcopyDataChannel", NULL, 0 }, 248 { 0x0016, "HardcopyNotification", NULL, 0 }, 249 { 0x0017, "AVCTP", NULL, 0 }, 250 { 0x0019, "AVDTP", NULL, 0 }, 251 { 0x001b, "CMTP", NULL, 0 }, 252 { 0x001d, "UDI_C-Plane", NULL, 0 }, 253 { 0x0100, "L2CAP", NULL, 0 }, 254 /* -- Services -- */ 255 { 0x1000, "ServiceDiscoveryServerServiceClassID", 256 sdp_attrib_names, sizeof(sdp_attrib_names)/sizeof(struct attrib_def) }, 257 { 0x1001, "BrowseGroupDescriptorServiceClassID", 258 browse_attrib_names, sizeof(browse_attrib_names)/sizeof(struct attrib_def) }, 259 { 0x1002, "PublicBrowseGroup", NULL, 0 }, 260 { 0x1101, "SerialPort", NULL, 0 }, 261 { 0x1102, "LANAccessUsingPPP", NULL, 0 }, 262 { 0x1103, "DialupNetworking (DUN)", NULL, 0 }, 263 { 0x1104, "IrMCSync", NULL, 0 }, 264 { 0x1105, "OBEXObjectPush", NULL, 0 }, 265 { 0x1106, "OBEXFileTransfer", NULL, 0 }, 266 { 0x1107, "IrMCSyncCommand", NULL, 0 }, 267 { 0x1108, "Headset", 268 audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) }, 269 { 0x1109, "CordlessTelephony", NULL, 0 }, 270 { 0x110a, "AudioSource", NULL, 0 }, 271 { 0x110b, "AudioSink", NULL, 0 }, 272 { 0x110c, "RemoteControlTarget", NULL, 0 }, 273 { 0x110d, "AdvancedAudio", NULL, 0 }, 274 { 0x110e, "RemoteControl", NULL, 0 }, 275 { 0x110f, "VideoConferencing", NULL, 0 }, 276 { 0x1110, "Intercom", NULL, 0 }, 277 { 0x1111, "Fax", NULL, 0 }, 278 { 0x1112, "HeadsetAudioGateway", NULL, 0 }, 279 { 0x1113, "WAP", NULL, 0 }, 280 { 0x1114, "WAP Client", NULL, 0 }, 281 { 0x1115, "PANU (PAN/BNEP)", 282 pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) }, 283 { 0x1116, "NAP (PAN/BNEP)", 284 pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) }, 285 { 0x1117, "GN (PAN/BNEP)", 286 pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) }, 287 { 0x1118, "DirectPrinting (BPP)", NULL, 0 }, 288 { 0x1119, "ReferencePrinting (BPP)", NULL, 0 }, 289 { 0x111a, "Imaging (BIP)", NULL, 0 }, 290 { 0x111b, "ImagingResponder (BIP)", NULL, 0 }, 291 { 0x111c, "ImagingAutomaticArchive (BIP)", NULL, 0 }, 292 { 0x111d, "ImagingReferencedObjects (BIP)", NULL, 0 }, 293 { 0x111e, "Handsfree", NULL, 0 }, 294 { 0x111f, "HandsfreeAudioGateway", NULL, 0 }, 295 { 0x1120, "DirectPrintingReferenceObjectsService (BPP)", NULL, 0 }, 296 { 0x1121, "ReflectedUI (BPP)", NULL, 0 }, 297 { 0x1122, "BasicPrinting (BPP)", NULL, 0 }, 298 { 0x1123, "PrintingStatus (BPP)", NULL, 0 }, 299 { 0x1124, "HumanInterfaceDeviceService (HID)", 300 hid_attrib_names, sizeof(hid_attrib_names)/sizeof(struct attrib_def) }, 301 { 0x1125, "HardcopyCableReplacement (HCR)", NULL, 0 }, 302 { 0x1126, "HCR_Print (HCR)", NULL, 0 }, 303 { 0x1127, "HCR_Scan (HCR)", NULL, 0 }, 304 { 0x1128, "Common ISDN Access (CIP)", NULL, 0 }, 305 { 0x1129, "VideoConferencingGW (VCP)", NULL, 0 }, 306 { 0x112a, "UDI-MT", NULL, 0 }, 307 { 0x112b, "UDI-TA", NULL, 0 }, 308 { 0x112c, "Audio/Video", NULL, 0 }, 309 { 0x112d, "SIM Access (SAP)", NULL, 0 }, 310 { 0x112e, "Phonebook Access (PBAP) - PCE", NULL, 0 }, 311 { 0x112f, "Phonebook Access (PBAP) - PSE", NULL, 0 }, 312 { 0x1130, "Phonebook Access (PBAP)", NULL, 0 }, 313 /* ... */ 314 { 0x1200, "PnPInformation", 315 did_attrib_names, sizeof(did_attrib_names)/sizeof(struct attrib_def) }, 316 { 0x1201, "GenericNetworking", NULL, 0 }, 317 { 0x1202, "GenericFileTransfer", NULL, 0 }, 318 { 0x1203, "GenericAudio", 319 audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) }, 320 { 0x1204, "GenericTelephony", NULL, 0 }, 321 /* ... */ 322 { 0x1303, "VideoSource", NULL, 0 }, 323 { 0x1304, "VideoSink", NULL, 0 }, 324 { 0x1305, "VideoDistribution", NULL, 0 }, 325 { 0x1400, "MDP", NULL, 0 }, 326 { 0x1401, "MDPSource", NULL, 0 }, 327 { 0x1402, "MDPSink", NULL, 0 }, 328 { 0x2112, "AppleAgent", NULL, 0 }, 329 }; 330 331 static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def); 332 333 static void sdp_data_printf(sdp_data_t *, struct attrib_context *, int); 334 335 /* 336 * Parse a UUID. 337 * The BT assigned numbers only list UUID16, so I'm not sure the 338 * other types will ever get used... 339 */ 340 static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent) 341 { 342 if (uuid) { 343 if (uuid->type == SDP_UUID16) { 344 uint16_t uuidNum = uuid->value.uuid16; 345 struct uuid_def *uuidDef = NULL; 346 int i; 347 348 for (i = 0; i < uuid16_max; i++) 349 if (uuid16_names[i].num == uuidNum) { 350 uuidDef = &uuid16_names[i]; 351 break; 352 } 353 354 /* Check if it's the service attribute */ 355 if (context->attrib && context->attrib->num == SERVICE_ATTR) { 356 /* We got the service ID !!! */ 357 context->service = uuidDef; 358 } 359 360 if (uuidDef) 361 printf("%.*sUUID16 : 0x%.4x - %s\n", 362 indent, indent_spaces, uuidNum, uuidDef->name); 363 else 364 printf("%.*sUUID16 : 0x%.4x\n", 365 indent, indent_spaces, uuidNum); 366 } else if (uuid->type == SDP_UUID32) { 367 struct uuid_def *uuidDef = NULL; 368 int i; 369 370 if (!(uuid->value.uuid32 & 0xffff0000)) { 371 uint16_t uuidNum = uuid->value.uuid32; 372 for (i = 0; i < uuid16_max; i++) 373 if (uuid16_names[i].num == uuidNum) { 374 uuidDef = &uuid16_names[i]; 375 break; 376 } 377 } 378 379 if (uuidDef) 380 printf("%.*sUUID32 : 0x%.8x - %s\n", 381 indent, indent_spaces, uuid->value.uuid32, uuidDef->name); 382 else 383 printf("%.*sUUID32 : 0x%.8x\n", 384 indent, indent_spaces, uuid->value.uuid32); 385 } else if (uuid->type == SDP_UUID128) { 386 unsigned int data0; 387 unsigned short data1; 388 unsigned short data2; 389 unsigned short data3; 390 unsigned int data4; 391 unsigned short data5; 392 393 memcpy(&data0, &uuid->value.uuid128.data[0], 4); 394 memcpy(&data1, &uuid->value.uuid128.data[4], 2); 395 memcpy(&data2, &uuid->value.uuid128.data[6], 2); 396 memcpy(&data3, &uuid->value.uuid128.data[8], 2); 397 memcpy(&data4, &uuid->value.uuid128.data[10], 4); 398 memcpy(&data5, &uuid->value.uuid128.data[14], 2); 399 400 printf("%.*sUUID128 : 0x%.8x-%.4x-%.4x-%.4x-%.8x-%.4x\n", 401 indent, indent_spaces, 402 ntohl(data0), ntohs(data1), ntohs(data2), 403 ntohs(data3), ntohl(data4), ntohs(data5)); 404 } else 405 printf("%.*sEnum type of UUID not set\n", 406 indent, indent_spaces); 407 } else 408 printf("%.*sNull passed to print UUID\n", 409 indent, indent_spaces); 410 } 411 412 /* 413 * Parse a sequence of data elements (i.e. a list) 414 */ 415 static void printf_dataseq(sdp_data_t * pData, struct attrib_context *context, int indent) 416 { 417 sdp_data_t *sdpdata = NULL; 418 419 sdpdata = pData; 420 if (sdpdata) { 421 context->member_index = 0; 422 do { 423 sdp_data_printf(sdpdata, context, indent + 2); 424 sdpdata = sdpdata->next; 425 context->member_index++; 426 } while (sdpdata); 427 } else { 428 printf("%.*sBroken dataseq link\n", indent, indent_spaces); 429 } 430 } 431 432 /* 433 * Parse a single data element (either in the attribute or in a data 434 * sequence). 435 */ 436 static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent) 437 { 438 char *member_name = NULL; 439 440 /* Find member name. Almost black magic ;-) */ 441 if (context && context->attrib && context->attrib->members && 442 context->member_index < context->attrib->member_max) { 443 member_name = context->attrib->members[context->member_index].name; 444 } 445 446 switch (sdpdata->dtd) { 447 case SDP_DATA_NIL: 448 printf("%.*sNil\n", indent, indent_spaces); 449 break; 450 case SDP_BOOL: 451 case SDP_UINT8: 452 case SDP_UINT16: 453 case SDP_UINT32: 454 case SDP_UINT64: 455 case SDP_UINT128: 456 case SDP_INT8: 457 case SDP_INT16: 458 case SDP_INT32: 459 case SDP_INT64: 460 case SDP_INT128: 461 if (member_name) { 462 printf("%.*s%s (Integer) : 0x%x\n", 463 indent, indent_spaces, member_name, sdpdata->val.uint32); 464 } else { 465 printf("%.*sInteger : 0x%x\n", indent, indent_spaces, 466 sdpdata->val.uint32); 467 } 468 break; 469 470 case SDP_UUID16: 471 case SDP_UUID32: 472 case SDP_UUID128: 473 //printf("%.*sUUID\n", indent, indent_spaces); 474 sdp_uuid_printf(&sdpdata->val.uuid, context, indent); 475 break; 476 477 case SDP_TEXT_STR8: 478 case SDP_TEXT_STR16: 479 case SDP_TEXT_STR32: 480 if (sdpdata->unitSize > (int) strlen(sdpdata->val.str)) { 481 int i; 482 printf("%.*sData :", indent, indent_spaces); 483 for (i = 0; i < sdpdata->unitSize; i++) 484 printf(" %02x", (unsigned char) sdpdata->val.str[i]); 485 printf("\n"); 486 } else 487 printf("%.*sText : \"%s\"\n", indent, indent_spaces, sdpdata->val.str); 488 break; 489 case SDP_URL_STR8: 490 case SDP_URL_STR16: 491 case SDP_URL_STR32: 492 printf("%.*sURL : %s\n", indent, indent_spaces, sdpdata->val.str); 493 break; 494 495 case SDP_SEQ8: 496 case SDP_SEQ16: 497 case SDP_SEQ32: 498 printf("%.*sData Sequence\n", indent, indent_spaces); 499 printf_dataseq(sdpdata->val.dataseq, context, indent); 500 break; 501 502 case SDP_ALT8: 503 case SDP_ALT16: 504 case SDP_ALT32: 505 printf("%.*sData Sequence Alternates\n", indent, indent_spaces); 506 printf_dataseq(sdpdata->val.dataseq, context, indent); 507 break; 508 } 509 } 510 511 /* 512 * Parse a single attribute. 513 */ 514 static void print_tree_attr_func(void *value, void *userData) 515 { 516 sdp_data_t *sdpdata = NULL; 517 uint16_t attrId; 518 struct service_context *service = (struct service_context *) userData; 519 struct attrib_context context; 520 struct attrib_def *attrDef = NULL; 521 int i; 522 523 sdpdata = (sdp_data_t *)value; 524 attrId = sdpdata->attrId; 525 /* Search amongst the generic attributes */ 526 for (i = 0; i < attrib_max; i++) 527 if (attrib_names[i].num == attrId) { 528 attrDef = &attrib_names[i]; 529 break; 530 } 531 /* Search amongst the specific attributes of this service */ 532 if ((attrDef == NULL) && (service->service != NULL) && 533 (service->service->attribs != NULL)) { 534 struct attrib_def *svc_attribs = service->service->attribs; 535 int svc_attrib_max = service->service->attrib_max; 536 for (i = 0; i < svc_attrib_max; i++) 537 if (svc_attribs[i].num == attrId) { 538 attrDef = &svc_attribs[i]; 539 break; 540 } 541 } 542 543 if (attrDef) 544 printf("Attribute Identifier : 0x%x - %s\n", attrId, attrDef->name); 545 else 546 printf("Attribute Identifier : 0x%x\n", attrId); 547 /* Build context */ 548 context.service = service->service; 549 context.attrib = attrDef; 550 context.member_index = 0; 551 /* Parse attribute members */ 552 if (sdpdata) 553 sdp_data_printf(sdpdata, &context, 2); 554 else 555 printf(" NULL value\n"); 556 /* Update service */ 557 service->service = context.service; 558 } 559 560 /* 561 * Main entry point of this library. Parse a SDP record. 562 * We assume the record has already been read, parsed and cached 563 * locally. Jean II 564 */ 565 static void print_tree_attr(sdp_record_t *rec) 566 { 567 if (rec && rec->attrlist) { 568 struct service_context service = { NULL }; 569 sdp_list_foreach(rec->attrlist, print_tree_attr_func, &service); 570 } 571 } 572 573 static void print_raw_data(sdp_data_t *data, int indent) 574 { 575 struct uuid_def *def; 576 int i, hex; 577 578 if (!data) 579 return; 580 581 for (i = 0; i < indent; i++) 582 printf("\t"); 583 584 switch (data->dtd) { 585 case SDP_DATA_NIL: 586 printf("NIL\n"); 587 break; 588 case SDP_BOOL: 589 printf("Bool %s\n", data->val.uint8 ? "True" : "False"); 590 break; 591 case SDP_UINT8: 592 printf("UINT8 0x%02x\n", data->val.uint8); 593 break; 594 case SDP_UINT16: 595 printf("UINT16 0x%04x\n", data->val.uint16); 596 break; 597 case SDP_UINT32: 598 printf("UINT32 0x%08x\n", data->val.uint32); 599 break; 600 case SDP_UINT64: 601 printf("UINT64 0x%016jx\n", data->val.uint64); 602 break; 603 case SDP_UINT128: 604 printf("UINT128 ...\n"); 605 break; 606 case SDP_INT8: 607 printf("INT8 %d\n", data->val.int8); 608 break; 609 case SDP_INT16: 610 printf("INT16 %d\n", data->val.int16); 611 break; 612 case SDP_INT32: 613 printf("INT32 %d\n", data->val.int32); 614 break; 615 case SDP_INT64: 616 printf("INT64 %jd\n", data->val.int64); 617 break; 618 case SDP_INT128: 619 printf("INT128 ...\n"); 620 break; 621 case SDP_UUID16: 622 case SDP_UUID32: 623 case SDP_UUID128: 624 switch (data->val.uuid.type) { 625 case SDP_UUID16: 626 def = NULL; 627 for (i = 0; i < uuid16_max; i++) 628 if (uuid16_names[i].num == data->val.uuid.value.uuid16) { 629 def = &uuid16_names[i]; 630 break; 631 } 632 if (def) 633 printf("UUID16 0x%04x - %s\n", data->val.uuid.value.uuid16, def->name); 634 else 635 printf("UUID16 0x%04x\n", data->val.uuid.value.uuid16); 636 break; 637 case SDP_UUID32: 638 def = NULL; 639 if (!(data->val.uuid.value.uuid32 & 0xffff0000)) { 640 uint16_t value = data->val.uuid.value.uuid32; 641 for (i = 0; i < uuid16_max; i++) 642 if (uuid16_names[i].num == value) { 643 def = &uuid16_names[i]; 644 break; 645 } 646 } 647 if (def) 648 printf("UUID32 0x%08x - %s\n", data->val.uuid.value.uuid32, def->name); 649 else 650 printf("UUID32 0x%08x\n", data->val.uuid.value.uuid32); 651 break; 652 case SDP_UUID128: 653 printf("UUID128 "); 654 for (i = 0; i < 16; i++) { 655 switch (i) { 656 case 4: 657 case 6: 658 case 8: 659 case 10: 660 printf("-"); 661 break; 662 } 663 printf("%02x", (unsigned char ) data->val.uuid.value.uuid128.data[i]); 664 } 665 printf("\n"); 666 break; 667 default: 668 printf("UUID type 0x%02x\n", data->val.uuid.type); 669 break; 670 } 671 break; 672 case SDP_TEXT_STR8: 673 case SDP_TEXT_STR16: 674 case SDP_TEXT_STR32: 675 hex = 0; 676 for (i = 0; i < data->unitSize; i++) { 677 if (i == (data->unitSize - 1) && data->val.str[i] == '\0') 678 break; 679 if (!isprint(data->val.str[i])) { 680 hex = 1; 681 break; 682 } 683 } 684 if (hex) { 685 printf("Data"); 686 for (i = 0; i < data->unitSize; i++) 687 printf(" %02x", (unsigned char) data->val.str[i]); 688 } else { 689 printf("String "); 690 for (i = 0; i < data->unitSize; i++) 691 printf("%c", data->val.str[i]); 692 } 693 printf("\n"); 694 break; 695 case SDP_URL_STR8: 696 case SDP_URL_STR16: 697 case SDP_URL_STR32: 698 printf("URL %s\n", data->val.str); 699 break; 700 case SDP_SEQ8: 701 case SDP_SEQ16: 702 case SDP_SEQ32: 703 printf("Sequence\n"); 704 print_raw_data(data->val.dataseq, indent + 1); 705 break; 706 case SDP_ALT8: 707 case SDP_ALT16: 708 case SDP_ALT32: 709 printf("Alternate\n"); 710 print_raw_data(data->val.dataseq, indent + 1); 711 break; 712 default: 713 printf("Unknown type 0x%02x\n", data->dtd); 714 break; 715 } 716 717 print_raw_data(data->next, indent); 718 } 719 720 static void print_raw_attr_func(void *value, void *userData) 721 { 722 sdp_data_t *data = (sdp_data_t *) value; 723 struct attrib_def *def = NULL; 724 int i; 725 726 /* Search amongst the generic attributes */ 727 for (i = 0; i < attrib_max; i++) 728 if (attrib_names[i].num == data->attrId) { 729 def = &attrib_names[i]; 730 break; 731 } 732 733 if (def) 734 printf("\tAttribute 0x%04x - %s\n", data->attrId, def->name); 735 else 736 printf("\tAttribute 0x%04x\n", data->attrId); 737 738 if (data) 739 print_raw_data(data, 2); 740 else 741 printf(" NULL value\n"); 742 } 743 744 static void print_raw_attr(sdp_record_t *rec) 745 { 746 if (rec && rec->attrlist) { 747 printf("Sequence\n"); 748 sdp_list_foreach(rec->attrlist, print_raw_attr_func, 0); 749 } 750 } 751 752 /* 753 * Set attributes with single values in SDP record 754 * Jean II 755 */ 756 static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *value) 757 { 758 sdp_list_t *attrid_list; 759 uint32_t range = 0x0000ffff; 760 sdp_record_t *rec; 761 int ret; 762 763 /* Get the old SDP record */ 764 attrid_list = sdp_list_append(NULL, &range); 765 rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attrid_list); 766 sdp_list_free(attrid_list, NULL); 767 768 if (!rec) { 769 printf("Service get request failed.\n"); 770 return -1; 771 } 772 773 /* Check the type of attribute */ 774 if (!strncasecmp(value, "u0x", 3)) { 775 /* UUID16 */ 776 uint16_t value_int = 0; 777 uuid_t value_uuid; 778 value_int = strtoul(value + 3, NULL, 16); 779 sdp_uuid16_create(&value_uuid, value_int); 780 printf("Adding attrib 0x%X uuid16 0x%X to record 0x%X\n", 781 attrib, value_int, handle); 782 783 sdp_attr_add_new(rec, attrib, SDP_UUID16, &value_uuid.value.uuid16); 784 } else if (!strncasecmp(value, "0x", 2)) { 785 /* Int */ 786 uint32_t value_int; 787 value_int = strtoul(value + 2, NULL, 16); 788 printf("Adding attrib 0x%X int 0x%X to record 0x%X\n", 789 attrib, value_int, handle); 790 791 sdp_attr_add_new(rec, attrib, SDP_UINT32, &value_int); 792 } else { 793 /* String */ 794 printf("Adding attrib 0x%X string \"%s\" to record 0x%X\n", 795 attrib, value, handle); 796 797 /* Add/Update our attribute to the record */ 798 sdp_attr_add_new(rec, attrib, SDP_TEXT_STR8, value); 799 } 800 801 /* Update on the server */ 802 ret = sdp_device_record_update(sess, &interface, rec); 803 if (ret < 0) 804 printf("Service Record update failed (%d).\n", errno); 805 sdp_record_free(rec); 806 return ret; 807 } 808 809 static struct option set_options[] = { 810 { "help", 0, 0, 'h' }, 811 { 0, 0, 0, 0 } 812 }; 813 814 static const char *set_help = 815 "Usage:\n" 816 "\tget record_handle attrib_id attrib_value\n"; 817 818 /* 819 * Add an attribute to an existing SDP record on the local SDP server 820 */ 821 static int cmd_setattr(int argc, char **argv) 822 { 823 int opt, status; 824 uint32_t handle; 825 uint16_t attrib; 826 sdp_session_t *sess; 827 828 for_each_opt(opt, set_options, NULL) { 829 switch(opt) { 830 default: 831 printf("%s", set_help); 832 return -1; 833 } 834 } 835 836 argc -= optind; 837 argv += optind; 838 839 if (argc < 3) { 840 printf("%s", set_help); 841 return -1; 842 } 843 844 /* Convert command line args */ 845 handle = strtoul(argv[0], NULL, 16); 846 attrib = strtoul(argv[1], NULL, 16); 847 848 /* Do it */ 849 sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); 850 if (!sess) 851 return -1; 852 853 status = set_attrib(sess, handle, attrib, argv[2]); 854 sdp_close(sess); 855 856 return status; 857 } 858 859 /* 860 * We do only simple data sequences. Sequence of sequences is a pain ;-) 861 * Jean II 862 */ 863 static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int argc, char **argv) 864 { 865 sdp_list_t *attrid_list; 866 uint32_t range = 0x0000ffff; 867 sdp_record_t *rec; 868 sdp_data_t *pSequenceHolder = NULL; 869 void **dtdArray; 870 void **valueArray; 871 void **allocArray; 872 uint8_t uuid16 = SDP_UUID16; 873 uint8_t uint32 = SDP_UINT32; 874 uint8_t str8 = SDP_TEXT_STR8; 875 int i, ret = 0; 876 877 /* Get the old SDP record */ 878 attrid_list = sdp_list_append(NULL, &range); 879 rec = sdp_service_attr_req(session, handle, SDP_ATTR_REQ_RANGE, attrid_list); 880 sdp_list_free(attrid_list, NULL); 881 882 if (!rec) { 883 printf("Service get request failed.\n"); 884 return -1; 885 } 886 887 /* Create arrays */ 888 dtdArray = (void **)malloc(argc * sizeof(void *)); 889 valueArray = (void **)malloc(argc * sizeof(void *)); 890 allocArray = (void **)malloc(argc * sizeof(void *)); 891 892 /* Loop on all args, add them in arrays */ 893 for (i = 0; i < argc; i++) { 894 /* Check the type of attribute */ 895 if (!strncasecmp(argv[i], "u0x", 3)) { 896 /* UUID16 */ 897 uint16_t value_int = strtoul((argv[i]) + 3, NULL, 16); 898 uuid_t *value_uuid = (uuid_t *) malloc(sizeof(uuid_t)); 899 allocArray[i] = value_uuid; 900 sdp_uuid16_create(value_uuid, value_int); 901 902 printf("Adding uuid16 0x%X to record 0x%X\n", value_int, handle); 903 dtdArray[i] = &uuid16; 904 valueArray[i] = &value_uuid->value.uuid16; 905 } else if (!strncasecmp(argv[i], "0x", 2)) { 906 /* Int */ 907 uint32_t *value_int = (uint32_t *) malloc(sizeof(int)); 908 allocArray[i] = value_int; 909 *value_int = strtoul((argv[i]) + 2, NULL, 16); 910 911 printf("Adding int 0x%X to record 0x%X\n", *value_int, handle); 912 dtdArray[i] = &uint32; 913 valueArray[i] = value_int; 914 } else { 915 /* String */ 916 printf("Adding string \"%s\" to record 0x%X\n", argv[i], handle); 917 dtdArray[i] = &str8; 918 valueArray[i] = argv[i]; 919 } 920 } 921 922 /* Add this sequence to the attrib list */ 923 pSequenceHolder = sdp_seq_alloc(dtdArray, valueArray, argc); 924 if (pSequenceHolder) { 925 sdp_attr_replace(rec, attrib, pSequenceHolder); 926 927 /* Update on the server */ 928 ret = sdp_device_record_update(session, &interface, rec); 929 if (ret < 0) 930 printf("Service Record update failed (%d).\n", errno); 931 } else 932 printf("Failed to create pSequenceHolder\n"); 933 934 /* Cleanup */ 935 for (i = 0; i < argc; i++) 936 free(allocArray[i]); 937 938 free(dtdArray); 939 free(valueArray); 940 free(allocArray); 941 942 sdp_record_free(rec); 943 944 return ret; 945 } 946 947 static struct option seq_options[] = { 948 { "help", 0, 0, 'h' }, 949 { 0, 0, 0, 0 } 950 }; 951 952 static const char *seq_help = 953 "Usage:\n" 954 "\tget record_handle attrib_id attrib_values\n"; 955 956 /* 957 * Add an attribute sequence to an existing SDP record 958 * on the local SDP server 959 */ 960 static int cmd_setseq(int argc, char **argv) 961 { 962 int opt, status; 963 uint32_t handle; 964 uint16_t attrib; 965 sdp_session_t *sess; 966 967 for_each_opt(opt, seq_options, NULL) { 968 switch(opt) { 969 default: 970 printf("%s", seq_help); 971 return -1; 972 } 973 } 974 975 argc -= optind; 976 argv += optind; 977 978 if (argc < 3) { 979 printf("%s", seq_help); 980 return -1; 981 } 982 983 /* Convert command line args */ 984 handle = strtoul(argv[0], NULL, 16); 985 attrib = strtoul(argv[1], NULL, 16); 986 987 argc -= 2; 988 argv += 2; 989 990 /* Do it */ 991 sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); 992 if (!sess) 993 return -1; 994 995 status = set_attribseq(sess, handle, attrib, argc, argv); 996 sdp_close(sess); 997 998 return status; 999 } 1000 1001 static void print_service_class(void *value, void *userData) 1002 { 1003 char ServiceClassUUID_str[MAX_LEN_SERVICECLASS_UUID_STR]; 1004 uuid_t *uuid = (uuid_t *)value; 1005 1006 sdp_uuid2strn(uuid, UUID_str, MAX_LEN_UUID_STR); 1007 sdp_svclass_uuid2strn(uuid, ServiceClassUUID_str, MAX_LEN_SERVICECLASS_UUID_STR); 1008 if (uuid->type != SDP_UUID128) 1009 printf(" \"%s\" (0x%s)\n", ServiceClassUUID_str, UUID_str); 1010 else 1011 printf(" UUID 128: %s\n", UUID_str); 1012 } 1013 1014 static void print_service_desc(void *value, void *user) 1015 { 1016 char str[MAX_LEN_PROTOCOL_UUID_STR]; 1017 sdp_data_t *p = (sdp_data_t *)value, *s; 1018 int i = 0, proto = 0; 1019 1020 for (; p; p = p->next, i++) { 1021 switch (p->dtd) { 1022 case SDP_UUID16: 1023 case SDP_UUID32: 1024 case SDP_UUID128: 1025 sdp_uuid2strn(&p->val.uuid, UUID_str, MAX_LEN_UUID_STR); 1026 sdp_proto_uuid2strn(&p->val.uuid, str, sizeof(str)); 1027 proto = sdp_uuid_to_proto(&p->val.uuid); 1028 printf(" \"%s\" (0x%s)\n", str, UUID_str); 1029 break; 1030 case SDP_UINT8: 1031 if (proto == RFCOMM_UUID) 1032 printf(" Channel: %d\n", p->val.uint8); 1033 else 1034 printf(" uint8: 0x%x\n", p->val.uint8); 1035 break; 1036 case SDP_UINT16: 1037 if (proto == L2CAP_UUID) { 1038 if (i == 1) 1039 printf(" PSM: %d\n", p->val.uint16); 1040 else 1041 printf(" Version: 0x%04x\n", p->val.uint16); 1042 } else if (proto == BNEP_UUID) 1043 if (i == 1) 1044 printf(" Version: 0x%04x\n", p->val.uint16); 1045 else 1046 printf(" uint16: 0x%x\n", p->val.uint16); 1047 else 1048 printf(" uint16: 0x%x\n", p->val.uint16); 1049 break; 1050 case SDP_SEQ16: 1051 printf(" SEQ16:"); 1052 for (s = p->val.dataseq; s; s = s->next) 1053 printf(" %x", s->val.uint16); 1054 printf("\n"); 1055 break; 1056 case SDP_SEQ8: 1057 printf(" SEQ8:"); 1058 for (s = p->val.dataseq; s; s = s->next) 1059 printf(" %x", s->val.uint8); 1060 printf("\n"); 1061 break; 1062 default: 1063 printf(" FIXME: dtd=0%x\n", p->dtd); 1064 break; 1065 } 1066 } 1067 } 1068 1069 static void print_lang_attr(void *value, void *user) 1070 { 1071 sdp_lang_attr_t *lang = (sdp_lang_attr_t *)value; 1072 printf(" code_ISO639: 0x%02x\n", lang->code_ISO639); 1073 printf(" encoding: 0x%02x\n", lang->encoding); 1074 printf(" base_offset: 0x%02x\n", lang->base_offset); 1075 } 1076 1077 static void print_access_protos(void *value, void *userData) 1078 { 1079 sdp_list_t *protDescSeq = (sdp_list_t *)value; 1080 sdp_list_foreach(protDescSeq, print_service_desc, 0); 1081 } 1082 1083 static void print_profile_desc(void *value, void *userData) 1084 { 1085 sdp_profile_desc_t *desc = (sdp_profile_desc_t *)value; 1086 char str[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR]; 1087 1088 sdp_uuid2strn(&desc->uuid, UUID_str, MAX_LEN_UUID_STR); 1089 sdp_profile_uuid2strn(&desc->uuid, str, MAX_LEN_PROFILEDESCRIPTOR_UUID_STR); 1090 1091 printf(" \"%s\" (0x%s)\n", str, UUID_str); 1092 if (desc->version) 1093 printf(" Version: 0x%04x\n", desc->version); 1094 } 1095 1096 /* 1097 * Parse a SDP record in user friendly form. 1098 */ 1099 static void print_service_attr(sdp_record_t *rec) 1100 { 1101 sdp_list_t *list = 0, *proto = 0; 1102 1103 sdp_record_print(rec); 1104 1105 printf("Service RecHandle: 0x%x\n", rec->handle); 1106 1107 if (sdp_get_service_classes(rec, &list) == 0) { 1108 printf("Service Class ID List:\n"); 1109 sdp_list_foreach(list, print_service_class, 0); 1110 sdp_list_free(list, free); 1111 } 1112 if (sdp_get_access_protos(rec, &proto) == 0) { 1113 printf("Protocol Descriptor List:\n"); 1114 sdp_list_foreach(proto, print_access_protos, 0); 1115 sdp_list_foreach(proto, (sdp_list_func_t)sdp_list_free, 0); 1116 sdp_list_free(proto, 0); 1117 } 1118 if (sdp_get_lang_attr(rec, &list) == 0) { 1119 printf("Language Base Attr List:\n"); 1120 sdp_list_foreach(list, print_lang_attr, 0); 1121 sdp_list_free(list, free); 1122 } 1123 if (sdp_get_profile_descs(rec, &list) == 0) { 1124 printf("Profile Descriptor List:\n"); 1125 sdp_list_foreach(list, print_profile_desc, 0); 1126 sdp_list_free(list, free); 1127 } 1128 } 1129 1130 /* 1131 * Support for Service (de)registration 1132 */ 1133 typedef struct { 1134 uint32_t handle; 1135 char *name; 1136 char *provider; 1137 char *desc; 1138 unsigned int class; 1139 unsigned int profile; 1140 uint16_t psm; 1141 uint8_t channel; 1142 uint8_t network; 1143 } svc_info_t; 1144 1145 static void add_lang_attr(sdp_record_t *r) 1146 { 1147 sdp_lang_attr_t base_lang; 1148 sdp_list_t *langs = 0; 1149 1150 /* UTF-8 MIBenum (http://www.iana.org/assignments/character-sets) */ 1151 base_lang.code_ISO639 = (0x65 << 8) | 0x6e; 1152 base_lang.encoding = 106; 1153 base_lang.base_offset = SDP_PRIMARY_LANG_BASE; 1154 langs = sdp_list_append(0, &base_lang); 1155 sdp_set_lang_attr(r, langs); 1156 sdp_list_free(langs, 0); 1157 } 1158 1159 static int add_sp(sdp_session_t *session, svc_info_t *si) 1160 { 1161 sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto; 1162 uuid_t root_uuid, sp_uuid, l2cap, rfcomm; 1163 sdp_profile_desc_t profile; 1164 sdp_record_t record; 1165 uint8_t u8 = si->channel ? si->channel : 1; 1166 sdp_data_t *channel; 1167 int ret = 0; 1168 1169 memset(&record, 0, sizeof(sdp_record_t)); 1170 record.handle = si->handle; 1171 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1172 root = sdp_list_append(0, &root_uuid); 1173 sdp_set_browse_groups(&record, root); 1174 sdp_list_free(root, 0); 1175 1176 sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID); 1177 svclass_id = sdp_list_append(0, &sp_uuid); 1178 sdp_set_service_classes(&record, svclass_id); 1179 sdp_list_free(svclass_id, 0); 1180 1181 sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); 1182 profile.version = 0x0100; 1183 profiles = sdp_list_append(0, &profile); 1184 sdp_set_profile_descs(&record, profiles); 1185 sdp_list_free(profiles, 0); 1186 1187 sdp_uuid16_create(&l2cap, L2CAP_UUID); 1188 proto[0] = sdp_list_append(0, &l2cap); 1189 apseq = sdp_list_append(0, proto[0]); 1190 1191 sdp_uuid16_create(&rfcomm, RFCOMM_UUID); 1192 proto[1] = sdp_list_append(0, &rfcomm); 1193 channel = sdp_data_alloc(SDP_UINT8, &u8); 1194 proto[1] = sdp_list_append(proto[1], channel); 1195 apseq = sdp_list_append(apseq, proto[1]); 1196 1197 aproto = sdp_list_append(0, apseq); 1198 sdp_set_access_protos(&record, aproto); 1199 1200 add_lang_attr(&record); 1201 1202 sdp_set_info_attr(&record, "Serial Port", "BlueZ", "COM Port"); 1203 1204 sdp_set_url_attr(&record, "http://www.bluez.org/", 1205 "http://www.bluez.org/", "http://www.bluez.org/"); 1206 1207 sdp_set_service_id(&record, sp_uuid); 1208 sdp_set_service_ttl(&record, 0xffff); 1209 sdp_set_service_avail(&record, 0xff); 1210 sdp_set_record_state(&record, 0x00001234); 1211 1212 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1213 printf("Service Record registration failed\n"); 1214 ret = -1; 1215 goto end; 1216 } 1217 1218 printf("Serial Port service registered\n"); 1219 1220 end: 1221 sdp_data_free(channel); 1222 sdp_list_free(proto[0], 0); 1223 sdp_list_free(proto[1], 0); 1224 sdp_list_free(apseq, 0); 1225 sdp_list_free(aproto, 0); 1226 1227 return ret; 1228 } 1229 1230 static int add_dun(sdp_session_t *session, svc_info_t *si) 1231 { 1232 sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto; 1233 uuid_t rootu, dun, gn, l2cap, rfcomm; 1234 sdp_profile_desc_t profile; 1235 sdp_list_t *proto[2]; 1236 sdp_record_t record; 1237 uint8_t u8 = si->channel ? si->channel : 2; 1238 sdp_data_t *channel; 1239 int ret = 0; 1240 1241 memset(&record, 0, sizeof(sdp_record_t)); 1242 record.handle = si->handle; 1243 1244 sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP); 1245 root = sdp_list_append(0, &rootu); 1246 sdp_set_browse_groups(&record, root); 1247 1248 sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID); 1249 svclass_id = sdp_list_append(0, &dun); 1250 sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID); 1251 svclass_id = sdp_list_append(svclass_id, &gn); 1252 sdp_set_service_classes(&record, svclass_id); 1253 1254 sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID); 1255 profile.version = 0x0100; 1256 pfseq = sdp_list_append(0, &profile); 1257 sdp_set_profile_descs(&record, pfseq); 1258 1259 sdp_uuid16_create(&l2cap, L2CAP_UUID); 1260 proto[0] = sdp_list_append(0, &l2cap); 1261 apseq = sdp_list_append(0, proto[0]); 1262 1263 sdp_uuid16_create(&rfcomm, RFCOMM_UUID); 1264 proto[1] = sdp_list_append(0, &rfcomm); 1265 channel = sdp_data_alloc(SDP_UINT8, &u8); 1266 proto[1] = sdp_list_append(proto[1], channel); 1267 apseq = sdp_list_append(apseq, proto[1]); 1268 1269 aproto = sdp_list_append(0, apseq); 1270 sdp_set_access_protos(&record, aproto); 1271 1272 sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0); 1273 1274 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1275 printf("Service Record registration failed\n"); 1276 ret = -1; 1277 goto end; 1278 } 1279 1280 printf("Dial-Up Networking service registered\n"); 1281 1282 end: 1283 sdp_data_free(channel); 1284 sdp_list_free(proto[0], 0); 1285 sdp_list_free(proto[1], 0); 1286 sdp_list_free(apseq, 0); 1287 sdp_list_free(aproto, 0); 1288 1289 return ret; 1290 } 1291 1292 static int add_fax(sdp_session_t *session, svc_info_t *si) 1293 { 1294 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1295 uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid; 1296 sdp_profile_desc_t profile; 1297 sdp_list_t *aproto, *proto[2]; 1298 sdp_record_t record; 1299 uint8_t u8 = si->channel? si->channel : 3; 1300 sdp_data_t *channel; 1301 int ret = 0; 1302 1303 memset(&record, 0, sizeof(sdp_record_t)); 1304 record.handle = si->handle; 1305 1306 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1307 root = sdp_list_append(0, &root_uuid); 1308 sdp_set_browse_groups(&record, root); 1309 1310 sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID); 1311 svclass_id = sdp_list_append(0, &fax_uuid); 1312 sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID); 1313 svclass_id = sdp_list_append(svclass_id, &tel_uuid); 1314 sdp_set_service_classes(&record, svclass_id); 1315 1316 sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID); 1317 profile.version = 0x0100; 1318 pfseq = sdp_list_append(0, &profile); 1319 sdp_set_profile_descs(&record, pfseq); 1320 1321 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1322 proto[0] = sdp_list_append(0, &l2cap_uuid); 1323 apseq = sdp_list_append(0, proto[0]); 1324 1325 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1326 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1327 channel = sdp_data_alloc(SDP_UINT8, &u8); 1328 proto[1] = sdp_list_append(proto[1], channel); 1329 apseq = sdp_list_append(apseq, proto[1]); 1330 1331 aproto = sdp_list_append(0, apseq); 1332 sdp_set_access_protos(&record, aproto); 1333 1334 sdp_set_info_attr(&record, "Fax", 0, 0); 1335 1336 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1337 printf("Service Record registration failed\n"); 1338 ret = -1; 1339 goto end; 1340 } 1341 printf("Fax service registered\n"); 1342 end: 1343 sdp_data_free(channel); 1344 sdp_list_free(proto[0], 0); 1345 sdp_list_free(proto[1], 0); 1346 sdp_list_free(apseq, 0); 1347 sdp_list_free(aproto, 0); 1348 return ret; 1349 } 1350 1351 static int add_lan(sdp_session_t *session, svc_info_t *si) 1352 { 1353 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1354 uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; 1355 sdp_profile_desc_t profile; 1356 sdp_list_t *aproto, *proto[2]; 1357 sdp_record_t record; 1358 uint8_t u8 = si->channel ? si->channel : 4; 1359 sdp_data_t *channel; 1360 int ret = 0; 1361 1362 memset(&record, 0, sizeof(sdp_record_t)); 1363 record.handle = si->handle; 1364 1365 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1366 root = sdp_list_append(0, &root_uuid); 1367 sdp_set_browse_groups(&record, root); 1368 1369 sdp_uuid16_create(&svclass_uuid, LAN_ACCESS_SVCLASS_ID); 1370 svclass_id = sdp_list_append(0, &svclass_uuid); 1371 sdp_set_service_classes(&record, svclass_id); 1372 1373 sdp_uuid16_create(&profile.uuid, LAN_ACCESS_PROFILE_ID); 1374 profile.version = 0x0100; 1375 pfseq = sdp_list_append(0, &profile); 1376 sdp_set_profile_descs(&record, pfseq); 1377 1378 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1379 proto[0] = sdp_list_append(0, &l2cap_uuid); 1380 apseq = sdp_list_append(0, proto[0]); 1381 1382 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1383 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1384 channel = sdp_data_alloc(SDP_UINT8, &u8); 1385 proto[1] = sdp_list_append(proto[1], channel); 1386 apseq = sdp_list_append(apseq, proto[1]); 1387 1388 aproto = sdp_list_append(0, apseq); 1389 sdp_set_access_protos(&record, aproto); 1390 1391 sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0); 1392 1393 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1394 printf("Service Record registration failed\n"); 1395 ret = -1; 1396 goto end; 1397 } 1398 1399 printf("LAN Access service registered\n"); 1400 1401 end: 1402 sdp_data_free(channel); 1403 sdp_list_free(proto[0], 0); 1404 sdp_list_free(proto[1], 0); 1405 sdp_list_free(apseq, 0); 1406 sdp_list_free(aproto, 0); 1407 1408 return ret; 1409 } 1410 1411 static int add_headset(sdp_session_t *session, svc_info_t *si) 1412 { 1413 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1414 uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; 1415 sdp_profile_desc_t profile; 1416 sdp_list_t *aproto, *proto[2]; 1417 sdp_record_t record; 1418 uint8_t u8 = si->channel ? si->channel : 5; 1419 sdp_data_t *channel; 1420 int ret = 0; 1421 1422 memset(&record, 0, sizeof(sdp_record_t)); 1423 record.handle = si->handle; 1424 1425 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1426 root = sdp_list_append(0, &root_uuid); 1427 sdp_set_browse_groups(&record, root); 1428 1429 sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID); 1430 svclass_id = sdp_list_append(0, &svclass_uuid); 1431 sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); 1432 svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); 1433 sdp_set_service_classes(&record, svclass_id); 1434 1435 sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID); 1436 profile.version = 0x0100; 1437 pfseq = sdp_list_append(0, &profile); 1438 sdp_set_profile_descs(&record, pfseq); 1439 1440 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1441 proto[0] = sdp_list_append(0, &l2cap_uuid); 1442 apseq = sdp_list_append(0, proto[0]); 1443 1444 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1445 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1446 channel = sdp_data_alloc(SDP_UINT8, &u8); 1447 proto[1] = sdp_list_append(proto[1], channel); 1448 apseq = sdp_list_append(apseq, proto[1]); 1449 1450 aproto = sdp_list_append(0, apseq); 1451 sdp_set_access_protos(&record, aproto); 1452 1453 sdp_set_info_attr(&record, "Headset", 0, 0); 1454 1455 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1456 printf("Service Record registration failed\n"); 1457 ret = -1; 1458 goto end; 1459 } 1460 1461 printf("Headset service registered\n"); 1462 1463 end: 1464 sdp_data_free(channel); 1465 sdp_list_free(proto[0], 0); 1466 sdp_list_free(proto[1], 0); 1467 sdp_list_free(apseq, 0); 1468 sdp_list_free(aproto, 0); 1469 1470 return ret; 1471 } 1472 1473 static int add_headset_ag(sdp_session_t *session, svc_info_t *si) 1474 { 1475 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1476 uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; 1477 sdp_profile_desc_t profile; 1478 sdp_list_t *aproto, *proto[2]; 1479 sdp_record_t record; 1480 uint8_t u8 = si->channel ? si->channel : 7; 1481 uint16_t u16 = 0x17; 1482 sdp_data_t *channel, *features; 1483 uint8_t netid = si->network ? si->network : 0x01; // ???? profile document 1484 sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); 1485 int ret = 0; 1486 1487 memset(&record, 0, sizeof(sdp_record_t)); 1488 record.handle = si->handle; 1489 1490 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1491 root = sdp_list_append(0, &root_uuid); 1492 sdp_set_browse_groups(&record, root); 1493 1494 sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID); 1495 svclass_id = sdp_list_append(0, &svclass_uuid); 1496 sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); 1497 svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); 1498 sdp_set_service_classes(&record, svclass_id); 1499 1500 sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID); 1501 profile.version = 0x0100; 1502 pfseq = sdp_list_append(0, &profile); 1503 sdp_set_profile_descs(&record, pfseq); 1504 1505 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1506 proto[0] = sdp_list_append(0, &l2cap_uuid); 1507 apseq = sdp_list_append(0, proto[0]); 1508 1509 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1510 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1511 channel = sdp_data_alloc(SDP_UINT8, &u8); 1512 proto[1] = sdp_list_append(proto[1], channel); 1513 apseq = sdp_list_append(apseq, proto[1]); 1514 1515 features = sdp_data_alloc(SDP_UINT16, &u16); 1516 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); 1517 1518 aproto = sdp_list_append(0, apseq); 1519 sdp_set_access_protos(&record, aproto); 1520 1521 sdp_set_info_attr(&record, "Voice Gateway", 0, 0); 1522 1523 sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); 1524 1525 if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { 1526 printf("Service Record registration failed\n"); 1527 ret = -1; 1528 goto end; 1529 } 1530 1531 printf("Headset AG service registered\n"); 1532 1533 end: 1534 sdp_data_free(channel); 1535 sdp_list_free(proto[0], 0); 1536 sdp_list_free(proto[1], 0); 1537 sdp_list_free(apseq, 0); 1538 sdp_list_free(aproto, 0); 1539 1540 return ret; 1541 } 1542 1543 static int add_handsfree(sdp_session_t *session, svc_info_t *si) 1544 { 1545 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1546 uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; 1547 sdp_profile_desc_t profile; 1548 sdp_list_t *aproto, *proto[2]; 1549 sdp_record_t record; 1550 uint8_t u8 = si->channel ? si->channel : 6; 1551 uint16_t u16 = 0x31; 1552 sdp_data_t *channel, *features; 1553 int ret = 0; 1554 1555 memset(&record, 0, sizeof(sdp_record_t)); 1556 record.handle = si->handle; 1557 1558 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1559 root = sdp_list_append(0, &root_uuid); 1560 sdp_set_browse_groups(&record, root); 1561 1562 sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID); 1563 svclass_id = sdp_list_append(0, &svclass_uuid); 1564 sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); 1565 svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); 1566 sdp_set_service_classes(&record, svclass_id); 1567 1568 sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID); 1569 profile.version = 0x0101; 1570 pfseq = sdp_list_append(0, &profile); 1571 sdp_set_profile_descs(&record, pfseq); 1572 1573 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1574 proto[0] = sdp_list_append(0, &l2cap_uuid); 1575 apseq = sdp_list_append(0, proto[0]); 1576 1577 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1578 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1579 channel = sdp_data_alloc(SDP_UINT8, &u8); 1580 proto[1] = sdp_list_append(proto[1], channel); 1581 apseq = sdp_list_append(apseq, proto[1]); 1582 1583 features = sdp_data_alloc(SDP_UINT16, &u16); 1584 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); 1585 1586 aproto = sdp_list_append(0, apseq); 1587 sdp_set_access_protos(&record, aproto); 1588 1589 sdp_set_info_attr(&record, "Handsfree", 0, 0); 1590 1591 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1592 printf("Service Record registration failed\n"); 1593 ret = -1; 1594 goto end; 1595 } 1596 1597 printf("Handsfree service registered\n"); 1598 1599 end: 1600 sdp_data_free(channel); 1601 sdp_list_free(proto[0], 0); 1602 sdp_list_free(proto[1], 0); 1603 sdp_list_free(apseq, 0); 1604 sdp_list_free(aproto, 0); 1605 1606 return ret; 1607 } 1608 1609 static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si) 1610 { 1611 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1612 uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; 1613 sdp_profile_desc_t profile; 1614 sdp_list_t *aproto, *proto[2]; 1615 sdp_record_t record; 1616 uint8_t u8 = si->channel ? si->channel : 7; 1617 uint16_t u16 = 0x17; 1618 #ifdef ANDROID 1619 u16 = 0x07; 1620 #endif 1621 sdp_data_t *channel, *features; 1622 uint8_t netid = si->network ? si->network : 0x01; // ???? profile document 1623 sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); 1624 int ret = 0; 1625 1626 memset(&record, 0, sizeof(sdp_record_t)); 1627 record.handle = si->handle; 1628 1629 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1630 root = sdp_list_append(0, &root_uuid); 1631 sdp_set_browse_groups(&record, root); 1632 1633 sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID); 1634 svclass_id = sdp_list_append(0, &svclass_uuid); 1635 sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); 1636 svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); 1637 sdp_set_service_classes(&record, svclass_id); 1638 1639 sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID); 1640 profile.version = 0x0105; 1641 pfseq = sdp_list_append(0, &profile); 1642 sdp_set_profile_descs(&record, pfseq); 1643 1644 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1645 proto[0] = sdp_list_append(0, &l2cap_uuid); 1646 apseq = sdp_list_append(0, proto[0]); 1647 1648 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1649 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1650 channel = sdp_data_alloc(SDP_UINT8, &u8); 1651 proto[1] = sdp_list_append(proto[1], channel); 1652 apseq = sdp_list_append(apseq, proto[1]); 1653 1654 features = sdp_data_alloc(SDP_UINT16, &u16); 1655 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); 1656 1657 aproto = sdp_list_append(0, apseq); 1658 sdp_set_access_protos(&record, aproto); 1659 1660 sdp_set_info_attr(&record, "Voice Gateway", 0, 0); 1661 1662 sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); 1663 1664 if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { 1665 printf("Service Record registration failed\n"); 1666 ret = -1; 1667 goto end; 1668 } 1669 1670 printf("Handsfree AG service registered\n"); 1671 1672 end: 1673 sdp_data_free(channel); 1674 sdp_list_free(proto[0], 0); 1675 sdp_list_free(proto[1], 0); 1676 sdp_list_free(apseq, 0); 1677 sdp_list_free(aproto, 0); 1678 1679 return ret; 1680 } 1681 1682 static int add_simaccess(sdp_session_t *session, svc_info_t *si) 1683 { 1684 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1685 uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; 1686 sdp_profile_desc_t profile; 1687 sdp_list_t *aproto, *proto[2]; 1688 sdp_record_t record; 1689 uint8_t u8 = si->channel? si->channel : 8; 1690 uint16_t u16 = 0x31; 1691 sdp_data_t *channel, *features; 1692 int ret = 0; 1693 1694 memset((void *)&record, 0, sizeof(sdp_record_t)); 1695 record.handle = si->handle; 1696 1697 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1698 root = sdp_list_append(0, &root_uuid); 1699 sdp_set_browse_groups(&record, root); 1700 1701 sdp_uuid16_create(&svclass_uuid, SAP_SVCLASS_ID); 1702 svclass_id = sdp_list_append(0, &svclass_uuid); 1703 sdp_uuid16_create(&ga_svclass_uuid, GENERIC_TELEPHONY_SVCLASS_ID); 1704 svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); 1705 sdp_set_service_classes(&record, svclass_id); 1706 1707 sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID); 1708 profile.version = 0x0101; 1709 pfseq = sdp_list_append(0, &profile); 1710 sdp_set_profile_descs(&record, pfseq); 1711 1712 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1713 proto[0] = sdp_list_append(0, &l2cap_uuid); 1714 apseq = sdp_list_append(0, proto[0]); 1715 1716 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1717 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1718 channel = sdp_data_alloc(SDP_UINT8, &u8); 1719 proto[1] = sdp_list_append(proto[1], channel); 1720 apseq = sdp_list_append(apseq, proto[1]); 1721 1722 features = sdp_data_alloc(SDP_UINT16, &u16); 1723 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); 1724 1725 aproto = sdp_list_append(0, apseq); 1726 sdp_set_access_protos(&record, aproto); 1727 1728 sdp_set_info_attr(&record, "SIM Access", 0, 0); 1729 1730 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1731 printf("Service Record registration failed\n"); 1732 ret = -1; 1733 goto end; 1734 } 1735 1736 printf("SIM Access service registered\n"); 1737 1738 end: 1739 sdp_data_free(channel); 1740 sdp_list_free(proto[0], 0); 1741 sdp_list_free(proto[1], 0); 1742 sdp_list_free(apseq, 0); 1743 sdp_list_free(aproto, 0); 1744 1745 return ret; 1746 } 1747 1748 static int add_opush(sdp_session_t *session, svc_info_t *si) 1749 { 1750 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1751 uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; 1752 sdp_profile_desc_t profile[1]; 1753 sdp_list_t *aproto, *proto[3]; 1754 sdp_record_t record; 1755 uint8_t chan = si->channel ? si->channel : 9; 1756 sdp_data_t *channel; 1757 uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xff }; 1758 void *dtds[sizeof(formats)], *values[sizeof(formats)]; 1759 unsigned int i; 1760 uint8_t dtd = SDP_UINT8; 1761 sdp_data_t *sflist; 1762 int ret = 0; 1763 1764 memset(&record, 0, sizeof(sdp_record_t)); 1765 record.handle = si->handle; 1766 1767 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1768 root = sdp_list_append(0, &root_uuid); 1769 sdp_set_browse_groups(&record, root); 1770 1771 sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID); 1772 svclass_id = sdp_list_append(0, &opush_uuid); 1773 sdp_set_service_classes(&record, svclass_id); 1774 1775 sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID); 1776 profile[0].version = 0x0100; 1777 pfseq = sdp_list_append(0, profile); 1778 sdp_set_profile_descs(&record, pfseq); 1779 1780 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1781 proto[0] = sdp_list_append(0, &l2cap_uuid); 1782 apseq = sdp_list_append(0, proto[0]); 1783 1784 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1785 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1786 channel = sdp_data_alloc(SDP_UINT8, &chan); 1787 proto[1] = sdp_list_append(proto[1], channel); 1788 apseq = sdp_list_append(apseq, proto[1]); 1789 1790 sdp_uuid16_create(&obex_uuid, OBEX_UUID); 1791 proto[2] = sdp_list_append(0, &obex_uuid); 1792 apseq = sdp_list_append(apseq, proto[2]); 1793 1794 aproto = sdp_list_append(0, apseq); 1795 sdp_set_access_protos(&record, aproto); 1796 1797 for (i = 0; i < sizeof(formats); i++) { 1798 dtds[i] = &dtd; 1799 values[i] = &formats[i]; 1800 } 1801 sflist = sdp_seq_alloc(dtds, values, sizeof(formats)); 1802 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist); 1803 1804 sdp_set_info_attr(&record, "OBEX Object Push", 0, 0); 1805 1806 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1807 printf("Service Record registration failed\n"); 1808 ret = -1; 1809 goto end; 1810 } 1811 1812 printf("OBEX Object Push service registered\n"); 1813 1814 end: 1815 sdp_data_free(channel); 1816 sdp_list_free(proto[0], 0); 1817 sdp_list_free(proto[1], 0); 1818 sdp_list_free(proto[2], 0); 1819 sdp_list_free(apseq, 0); 1820 sdp_list_free(aproto, 0); 1821 1822 return ret; 1823 } 1824 1825 static int add_pbap(sdp_session_t *session, svc_info_t *si) 1826 { 1827 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1828 uuid_t root_uuid, pbap_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; 1829 sdp_profile_desc_t profile[1]; 1830 sdp_list_t *aproto, *proto[3]; 1831 sdp_record_t record; 1832 uint8_t chan = si->channel ? si->channel : 19; 1833 sdp_data_t *channel; 1834 uint8_t formats[] = {0x01}; 1835 void *dtds[sizeof(formats)], *values[sizeof(formats)]; 1836 int i; 1837 uint8_t dtd = SDP_UINT8; 1838 sdp_data_t *sflist; 1839 int ret = 0; 1840 1841 memset(&record, 0, sizeof(sdp_record_t)); 1842 record.handle = si->handle; 1843 1844 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1845 root = sdp_list_append(0, &root_uuid); 1846 sdp_set_browse_groups(&record, root); 1847 1848 sdp_uuid16_create(&pbap_uuid, PBAP_PSE_SVCLASS_ID); 1849 svclass_id = sdp_list_append(0, &pbap_uuid); 1850 sdp_set_service_classes(&record, svclass_id); 1851 1852 sdp_uuid16_create(&profile[0].uuid, PBAP_PROFILE_ID); 1853 profile[0].version = 0x0100; 1854 pfseq = sdp_list_append(0, profile); 1855 sdp_set_profile_descs(&record, pfseq); 1856 1857 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1858 proto[0] = sdp_list_append(0, &l2cap_uuid); 1859 apseq = sdp_list_append(0, proto[0]); 1860 1861 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1862 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1863 channel = sdp_data_alloc(SDP_UINT8, &chan); 1864 proto[1] = sdp_list_append(proto[1], channel); 1865 apseq = sdp_list_append(apseq, proto[1]); 1866 1867 sdp_uuid16_create(&obex_uuid, OBEX_UUID); 1868 proto[2] = sdp_list_append(0, &obex_uuid); 1869 apseq = sdp_list_append(apseq, proto[2]); 1870 1871 aproto = sdp_list_append(0, apseq); 1872 sdp_set_access_protos(&record, aproto); 1873 1874 sflist = sdp_data_alloc(dtd,formats); 1875 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_REPOSITORIES, sflist); 1876 1877 sdp_set_info_attr(&record, "OBEX Phonebook Access Server", 0, 0); 1878 1879 if (sdp_device_record_register(session, &interface, &record, 1880 SDP_RECORD_PERSIST) < 0) { 1881 printf("Service Record registration failed\n"); 1882 ret = -1; 1883 goto end; 1884 } 1885 1886 printf("PBAP service registered\n"); 1887 1888 end: 1889 sdp_data_free(channel); 1890 sdp_list_free(proto[0], 0); 1891 sdp_list_free(proto[1], 0); 1892 sdp_list_free(proto[2], 0); 1893 sdp_list_free(apseq, 0); 1894 sdp_list_free(aproto, 0); 1895 1896 return ret; 1897 } 1898 1899 static int add_ftp(sdp_session_t *session, svc_info_t *si) 1900 { 1901 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1902 uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; 1903 sdp_profile_desc_t profile[1]; 1904 sdp_list_t *aproto, *proto[3]; 1905 sdp_record_t record; 1906 uint8_t u8 = si->channel ? si->channel: 10; 1907 sdp_data_t *channel; 1908 int ret = 0; 1909 1910 memset(&record, 0, sizeof(sdp_record_t)); 1911 record.handle = si->handle; 1912 1913 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1914 root = sdp_list_append(0, &root_uuid); 1915 sdp_set_browse_groups(&record, root); 1916 1917 sdp_uuid16_create(&ftrn_uuid, OBEX_FILETRANS_SVCLASS_ID); 1918 svclass_id = sdp_list_append(0, &ftrn_uuid); 1919 sdp_set_service_classes(&record, svclass_id); 1920 1921 sdp_uuid16_create(&profile[0].uuid, OBEX_FILETRANS_PROFILE_ID); 1922 profile[0].version = 0x0100; 1923 pfseq = sdp_list_append(0, &profile[0]); 1924 sdp_set_profile_descs(&record, pfseq); 1925 1926 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1927 proto[0] = sdp_list_append(0, &l2cap_uuid); 1928 apseq = sdp_list_append(0, proto[0]); 1929 1930 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1931 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1932 channel = sdp_data_alloc(SDP_UINT8, &u8); 1933 proto[1] = sdp_list_append(proto[1], channel); 1934 apseq = sdp_list_append(apseq, proto[1]); 1935 1936 sdp_uuid16_create(&obex_uuid, OBEX_UUID); 1937 proto[2] = sdp_list_append(0, &obex_uuid); 1938 apseq = sdp_list_append(apseq, proto[2]); 1939 1940 aproto = sdp_list_append(0, apseq); 1941 sdp_set_access_protos(&record, aproto); 1942 1943 sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0); 1944 1945 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 1946 printf("Service Record registration failed\n"); 1947 ret = -1; 1948 goto end; 1949 } 1950 1951 printf("OBEX File Transfer service registered\n"); 1952 1953 end: 1954 sdp_data_free(channel); 1955 sdp_list_free(proto[0], 0); 1956 sdp_list_free(proto[1], 0); 1957 sdp_list_free(proto[2], 0); 1958 sdp_list_free(apseq, 0); 1959 sdp_list_free(aproto, 0); 1960 1961 return ret; 1962 } 1963 1964 static int add_directprint(sdp_session_t *session, svc_info_t *si) 1965 { 1966 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 1967 uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; 1968 sdp_profile_desc_t profile[1]; 1969 sdp_list_t *aproto, *proto[3]; 1970 sdp_record_t record; 1971 uint8_t chan = si->channel ? si->channel : 12; 1972 sdp_data_t *channel; 1973 int ret = 0; 1974 1975 memset(&record, 0, sizeof(sdp_record_t)); 1976 record.handle = si->handle; 1977 1978 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 1979 root = sdp_list_append(0, &root_uuid); 1980 sdp_set_browse_groups(&record, root); 1981 1982 sdp_uuid16_create(&opush_uuid, DIRECT_PRINTING_SVCLASS_ID); 1983 svclass_id = sdp_list_append(0, &opush_uuid); 1984 sdp_set_service_classes(&record, svclass_id); 1985 1986 sdp_uuid16_create(&profile[0].uuid, BASIC_PRINTING_PROFILE_ID); 1987 profile[0].version = 0x0100; 1988 pfseq = sdp_list_append(0, profile); 1989 sdp_set_profile_descs(&record, pfseq); 1990 1991 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 1992 proto[0] = sdp_list_append(0, &l2cap_uuid); 1993 apseq = sdp_list_append(0, proto[0]); 1994 1995 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 1996 proto[1] = sdp_list_append(0, &rfcomm_uuid); 1997 channel = sdp_data_alloc(SDP_UINT8, &chan); 1998 proto[1] = sdp_list_append(proto[1], channel); 1999 apseq = sdp_list_append(apseq, proto[1]); 2000 2001 sdp_uuid16_create(&obex_uuid, OBEX_UUID); 2002 proto[2] = sdp_list_append(0, &obex_uuid); 2003 apseq = sdp_list_append(apseq, proto[2]); 2004 2005 aproto = sdp_list_append(0, apseq); 2006 sdp_set_access_protos(&record, aproto); 2007 2008 sdp_set_info_attr(&record, "Direct Printing", 0, 0); 2009 2010 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2011 printf("Service Record registration failed\n"); 2012 ret = -1; 2013 goto end; 2014 } 2015 2016 printf("Direct Printing service registered\n"); 2017 2018 end: 2019 sdp_data_free(channel); 2020 sdp_list_free(proto[0], 0); 2021 sdp_list_free(proto[1], 0); 2022 sdp_list_free(proto[2], 0); 2023 sdp_list_free(apseq, 0); 2024 sdp_list_free(aproto, 0); 2025 2026 return ret; 2027 } 2028 2029 static int add_nap(sdp_session_t *session, svc_info_t *si) 2030 { 2031 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2032 uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid; 2033 sdp_profile_desc_t profile[1]; 2034 sdp_list_t *aproto, *proto[2]; 2035 sdp_record_t record; 2036 uint16_t lp = 0x000f, ver = 0x0100; 2037 sdp_data_t *psm, *version; 2038 int ret = 0; 2039 2040 memset(&record, 0, sizeof(sdp_record_t)); 2041 record.handle = si->handle; 2042 2043 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2044 root = sdp_list_append(0, &root_uuid); 2045 sdp_set_browse_groups(&record, root); 2046 2047 sdp_uuid16_create(&ftrn_uuid, NAP_SVCLASS_ID); 2048 svclass_id = sdp_list_append(0, &ftrn_uuid); 2049 sdp_set_service_classes(&record, svclass_id); 2050 2051 sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID); 2052 profile[0].version = 0x0100; 2053 pfseq = sdp_list_append(0, &profile[0]); 2054 sdp_set_profile_descs(&record, pfseq); 2055 2056 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 2057 proto[0] = sdp_list_append(0, &l2cap_uuid); 2058 psm = sdp_data_alloc(SDP_UINT16, &lp); 2059 proto[0] = sdp_list_append(proto[0], psm); 2060 apseq = sdp_list_append(0, proto[0]); 2061 2062 sdp_uuid16_create(&bnep_uuid, BNEP_UUID); 2063 proto[1] = sdp_list_append(0, &bnep_uuid); 2064 version = sdp_data_alloc(SDP_UINT16, &ver); 2065 proto[1] = sdp_list_append(proto[1], version); 2066 2067 { 2068 uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 }; 2069 sdp_data_t *head, *pseq; 2070 int p; 2071 2072 for (p = 0, head = NULL; p < 4; p++) { 2073 sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]); 2074 head = sdp_seq_append(head, data); 2075 } 2076 pseq = sdp_data_alloc(SDP_SEQ16, head); 2077 proto[1] = sdp_list_append(proto[1], pseq); 2078 } 2079 2080 apseq = sdp_list_append(apseq, proto[1]); 2081 2082 aproto = sdp_list_append(0, apseq); 2083 sdp_set_access_protos(&record, aproto); 2084 2085 sdp_set_info_attr(&record, "Network Access Point Service", 0, 0); 2086 2087 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2088 printf("Service Record registration failed\n"); 2089 ret = -1; 2090 goto end; 2091 } 2092 2093 printf("NAP service registered\n"); 2094 2095 end: 2096 sdp_data_free(version); 2097 sdp_data_free(psm); 2098 sdp_list_free(proto[0], 0); 2099 sdp_list_free(proto[1], 0); 2100 sdp_list_free(apseq, 0); 2101 sdp_list_free(aproto, 0); 2102 2103 return ret; 2104 } 2105 2106 static int add_gn(sdp_session_t *session, svc_info_t *si) 2107 { 2108 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2109 uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid; 2110 sdp_profile_desc_t profile[1]; 2111 sdp_list_t *aproto, *proto[2]; 2112 sdp_record_t record; 2113 uint16_t lp = 0x000f, ver = 0x0100; 2114 sdp_data_t *psm, *version; 2115 int ret = 0; 2116 2117 memset(&record, 0, sizeof(sdp_record_t)); 2118 record.handle = si->handle; 2119 2120 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2121 root = sdp_list_append(0, &root_uuid); 2122 sdp_set_browse_groups(&record, root); 2123 2124 sdp_uuid16_create(&ftrn_uuid, GN_SVCLASS_ID); 2125 svclass_id = sdp_list_append(0, &ftrn_uuid); 2126 sdp_set_service_classes(&record, svclass_id); 2127 2128 sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID); 2129 profile[0].version = 0x0100; 2130 pfseq = sdp_list_append(0, &profile[0]); 2131 sdp_set_profile_descs(&record, pfseq); 2132 2133 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 2134 proto[0] = sdp_list_append(0, &l2cap_uuid); 2135 psm = sdp_data_alloc(SDP_UINT16, &lp); 2136 proto[0] = sdp_list_append(proto[0], psm); 2137 apseq = sdp_list_append(0, proto[0]); 2138 2139 sdp_uuid16_create(&bnep_uuid, BNEP_UUID); 2140 proto[1] = sdp_list_append(0, &bnep_uuid); 2141 version = sdp_data_alloc(SDP_UINT16, &ver); 2142 proto[1] = sdp_list_append(proto[1], version); 2143 apseq = sdp_list_append(apseq, proto[1]); 2144 2145 aproto = sdp_list_append(0, apseq); 2146 sdp_set_access_protos(&record, aproto); 2147 2148 sdp_set_info_attr(&record, "Group Network Service", 0, 0); 2149 2150 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2151 printf("Service Record registration failed\n"); 2152 ret = -1; 2153 goto end; 2154 } 2155 2156 printf("GN service registered\n"); 2157 2158 end: 2159 sdp_data_free(version); 2160 sdp_data_free(psm); 2161 sdp_list_free(proto[0], 0); 2162 sdp_list_free(proto[1], 0); 2163 sdp_list_free(apseq, 0); 2164 sdp_list_free(aproto, 0); 2165 2166 return ret; 2167 } 2168 2169 static int add_panu(sdp_session_t *session, svc_info_t *si) 2170 { 2171 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2172 uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid; 2173 sdp_profile_desc_t profile[1]; 2174 sdp_list_t *aproto, *proto[2]; 2175 sdp_record_t record; 2176 uint16_t lp = 0x000f, ver = 0x0100; 2177 sdp_data_t *psm, *version; 2178 int ret = 0; 2179 2180 memset(&record, 0, sizeof(sdp_record_t)); 2181 record.handle = si->handle; 2182 2183 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2184 root = sdp_list_append(NULL, &root_uuid); 2185 sdp_set_browse_groups(&record, root); 2186 sdp_list_free(root, NULL); 2187 2188 sdp_uuid16_create(&ftrn_uuid, PANU_SVCLASS_ID); 2189 svclass_id = sdp_list_append(NULL, &ftrn_uuid); 2190 sdp_set_service_classes(&record, svclass_id); 2191 sdp_list_free(svclass_id, NULL); 2192 2193 sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID); 2194 profile[0].version = 0x0100; 2195 pfseq = sdp_list_append(NULL, &profile[0]); 2196 sdp_set_profile_descs(&record, pfseq); 2197 sdp_list_free(pfseq, NULL); 2198 2199 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 2200 proto[0] = sdp_list_append(NULL, &l2cap_uuid); 2201 psm = sdp_data_alloc(SDP_UINT16, &lp); 2202 proto[0] = sdp_list_append(proto[0], psm); 2203 apseq = sdp_list_append(NULL, proto[0]); 2204 2205 sdp_uuid16_create(&bnep_uuid, BNEP_UUID); 2206 proto[1] = sdp_list_append(NULL, &bnep_uuid); 2207 version = sdp_data_alloc(SDP_UINT16, &ver); 2208 proto[1] = sdp_list_append(proto[1], version); 2209 apseq = sdp_list_append(apseq, proto[1]); 2210 2211 aproto = sdp_list_append(NULL, apseq); 2212 sdp_set_access_protos(&record, aproto); 2213 2214 sdp_set_info_attr(&record, "PAN User", NULL, NULL); 2215 2216 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2217 printf("Service Record registration failed\n"); 2218 ret = -1; 2219 goto end; 2220 } 2221 2222 printf("PANU service registered\n"); 2223 2224 end: 2225 sdp_data_free(version); 2226 sdp_data_free(psm); 2227 sdp_list_free(proto[0], 0); 2228 sdp_list_free(proto[1], 0); 2229 sdp_list_free(apseq, 0); 2230 sdp_list_free(aproto, 0); 2231 2232 return ret; 2233 } 2234 2235 static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) 2236 { 2237 sdp_record_t record; 2238 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2239 uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid; 2240 sdp_profile_desc_t profile[1]; 2241 sdp_list_t *aproto, *proto[3]; 2242 sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2; 2243 unsigned int i; 2244 uint8_t dtd = SDP_UINT16; 2245 uint8_t dtd2 = SDP_UINT8; 2246 uint8_t dtd_data = SDP_TEXT_STR8; 2247 void *dtds[2]; 2248 void *values[2]; 2249 void *dtds2[2]; 2250 void *values2[2]; 2251 int leng[2]; 2252 uint8_t hid_spec_type = 0x22; 2253 uint16_t hid_attr_lang[] = { 0x409, 0x100 }; 2254 static const uint16_t ctrl = 0x11; 2255 static const uint16_t intr = 0x13; 2256 static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 }; 2257 static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 }; 2258 const uint8_t hid_spec[] = { 2259 0x05, 0x01, // usage page 2260 0x09, 0x06, // keyboard 2261 0xa1, 0x01, // key codes 2262 0x85, 0x01, // minimum 2263 0x05, 0x07, // max 2264 0x19, 0xe0, // logical min 2265 0x29, 0xe7, // logical max 2266 0x15, 0x00, // report size 2267 0x25, 0x01, // report count 2268 0x75, 0x01, // input data variable absolute 2269 0x95, 0x08, // report count 2270 0x81, 0x02, // report size 2271 0x75, 0x08, 2272 0x95, 0x01, 2273 0x81, 0x01, 2274 0x75, 0x01, 2275 0x95, 0x05, 2276 0x05, 0x08, 2277 0x19, 0x01, 2278 0x29, 0x05, 2279 0x91, 0x02, 2280 0x75, 0x03, 2281 0x95, 0x01, 2282 0x91, 0x01, 2283 0x75, 0x08, 2284 0x95, 0x06, 2285 0x15, 0x00, 2286 0x26, 0xff, 2287 0x00, 0x05, 2288 0x07, 0x19, 2289 0x00, 0x2a, 2290 0xff, 0x00, 2291 0x81, 0x00, 2292 0x75, 0x01, 2293 0x95, 0x01, 2294 0x15, 0x00, 2295 0x25, 0x01, 2296 0x05, 0x0c, 2297 0x09, 0xb8, 2298 0x81, 0x06, 2299 0x09, 0xe2, 2300 0x81, 0x06, 2301 0x09, 0xe9, 2302 0x81, 0x02, 2303 0x09, 0xea, 2304 0x81, 0x02, 2305 0x75, 0x01, 2306 0x95, 0x04, 2307 0x81, 0x01, 2308 0xc0 // end tag 2309 }; 2310 2311 memset(&record, 0, sizeof(sdp_record_t)); 2312 record.handle = si->handle; 2313 2314 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2315 root = sdp_list_append(0, &root_uuid); 2316 sdp_set_browse_groups(&record, root); 2317 2318 add_lang_attr(&record); 2319 2320 sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID); 2321 svclass_id = sdp_list_append(0, &hidkb_uuid); 2322 sdp_set_service_classes(&record, svclass_id); 2323 2324 sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID); 2325 profile[0].version = 0x0100; 2326 pfseq = sdp_list_append(0, profile); 2327 sdp_set_profile_descs(&record, pfseq); 2328 2329 /* protocols */ 2330 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 2331 proto[1] = sdp_list_append(0, &l2cap_uuid); 2332 psm = sdp_data_alloc(SDP_UINT16, &ctrl); 2333 proto[1] = sdp_list_append(proto[1], psm); 2334 apseq = sdp_list_append(0, proto[1]); 2335 2336 sdp_uuid16_create(&hidp_uuid, HIDP_UUID); 2337 proto[2] = sdp_list_append(0, &hidp_uuid); 2338 apseq = sdp_list_append(apseq, proto[2]); 2339 2340 aproto = sdp_list_append(0, apseq); 2341 sdp_set_access_protos(&record, aproto); 2342 2343 /* additional protocols */ 2344 proto[1] = sdp_list_append(0, &l2cap_uuid); 2345 psm = sdp_data_alloc(SDP_UINT16, &intr); 2346 proto[1] = sdp_list_append(proto[1], psm); 2347 apseq = sdp_list_append(0, proto[1]); 2348 2349 sdp_uuid16_create(&hidp_uuid, HIDP_UUID); 2350 proto[2] = sdp_list_append(0, &hidp_uuid); 2351 apseq = sdp_list_append(apseq, proto[2]); 2352 2353 aproto = sdp_list_append(0, apseq); 2354 sdp_set_add_access_protos(&record, aproto); 2355 2356 sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL); 2357 2358 for (i = 0; i < sizeof(hid_attr) / 2; i++) 2359 sdp_attr_add_new(&record, 2360 SDP_ATTR_HID_DEVICE_RELEASE_NUMBER + i, 2361 SDP_UINT16, &hid_attr[i]); 2362 2363 dtds[0] = &dtd2; 2364 values[0] = &hid_spec_type; 2365 dtds[1] = &dtd_data; 2366 values[1] = (uint8_t *) hid_spec; 2367 leng[0] = 0; 2368 leng[1] = sizeof(hid_spec); 2369 hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2); 2370 hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst); 2371 sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2); 2372 2373 for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) { 2374 dtds2[i] = &dtd; 2375 values2[i] = &hid_attr_lang[i]; 2376 } 2377 2378 lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2); 2379 lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst); 2380 sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2); 2381 2382 sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]); 2383 2384 for (i = 0; i < sizeof(hid_attr2) / 2 - 1; i++) 2385 sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP + i, 2386 SDP_UINT16, &hid_attr2[i + 1]); 2387 2388 if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { 2389 printf("Service Record registration failed\n"); 2390 return -1; 2391 } 2392 2393 printf("HID keyboard service registered\n"); 2394 2395 return 0; 2396 } 2397 2398 static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si) 2399 { 2400 sdp_record_t record; 2401 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2402 uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid; 2403 sdp_profile_desc_t profile[1]; 2404 sdp_list_t *aproto, *proto[3]; 2405 sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2; 2406 unsigned int i; 2407 uint8_t dtd = SDP_UINT16; 2408 uint8_t dtd2 = SDP_UINT8; 2409 uint8_t dtd_data = SDP_TEXT_STR8; 2410 void *dtds[2]; 2411 void *values[2]; 2412 void *dtds2[2]; 2413 void *values2[2]; 2414 int leng[2]; 2415 uint8_t hid_spec_type = 0x22; 2416 uint16_t hid_attr_lang[] = { 0x409, 0x100 }; 2417 uint16_t ctrl = 0x11, intr = 0x13; 2418 uint16_t hid_release = 0x0100, parser_version = 0x0111; 2419 uint8_t subclass = 0x04, country = 0x33; 2420 uint8_t virtual_cable = 0, reconnect = 1, sdp_disable = 0; 2421 uint8_t battery = 1, remote_wakeup = 1; 2422 uint16_t profile_version = 0x0100, superv_timeout = 0x0c80; 2423 uint8_t norm_connect = 0, boot_device = 0; 2424 const uint8_t hid_spec[] = { 2425 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10, 2426 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 2427 0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00, 2428 0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, 2429 0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00, 2430 0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, 2431 0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, 2432 0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, 2433 0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00, 2434 0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00, 2435 0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00, 2436 0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, 2437 0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, 2438 0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00, 2439 0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2440 0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00, 2441 0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00, 2442 0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00, 2443 0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00, 2444 0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00, 2445 0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2446 0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2447 0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2448 0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2449 0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2450 0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2451 0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, 2452 0xc0, 0x00 2453 }; 2454 2455 memset(&record, 0, sizeof(sdp_record_t)); 2456 record.handle = si->handle; 2457 2458 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2459 root = sdp_list_append(NULL, &root_uuid); 2460 sdp_set_browse_groups(&record, root); 2461 2462 sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID); 2463 svclass_id = sdp_list_append(NULL, &hid_uuid); 2464 sdp_set_service_classes(&record, svclass_id); 2465 2466 sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID); 2467 profile[0].version = 0x0100; 2468 pfseq = sdp_list_append(NULL, profile); 2469 sdp_set_profile_descs(&record, pfseq); 2470 2471 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 2472 proto[1] = sdp_list_append(0, &l2cap_uuid); 2473 psm = sdp_data_alloc(SDP_UINT16, &ctrl); 2474 proto[1] = sdp_list_append(proto[1], psm); 2475 apseq = sdp_list_append(0, proto[1]); 2476 2477 sdp_uuid16_create(&hidp_uuid, HIDP_UUID); 2478 proto[2] = sdp_list_append(0, &hidp_uuid); 2479 apseq = sdp_list_append(apseq, proto[2]); 2480 2481 aproto = sdp_list_append(0, apseq); 2482 sdp_set_access_protos(&record, aproto); 2483 2484 proto[1] = sdp_list_append(0, &l2cap_uuid); 2485 psm = sdp_data_alloc(SDP_UINT16, &intr); 2486 proto[1] = sdp_list_append(proto[1], psm); 2487 apseq = sdp_list_append(0, proto[1]); 2488 2489 sdp_uuid16_create(&hidp_uuid, HIDP_UUID); 2490 proto[2] = sdp_list_append(0, &hidp_uuid); 2491 apseq = sdp_list_append(apseq, proto[2]); 2492 2493 aproto = sdp_list_append(0, apseq); 2494 sdp_set_add_access_protos(&record, aproto); 2495 2496 add_lang_attr(&record); 2497 2498 sdp_set_info_attr(&record, "Nintendo RVL-CNT-01", 2499 "Nintendo", "Nintendo RVL-CNT-01"); 2500 2501 sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER, 2502 SDP_UINT16, &hid_release); 2503 2504 sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION, 2505 SDP_UINT16, &parser_version); 2506 2507 sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS, 2508 SDP_UINT8, &subclass); 2509 2510 sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE, 2511 SDP_UINT8, &country); 2512 2513 sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE, 2514 SDP_BOOL, &virtual_cable); 2515 2516 sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE, 2517 SDP_BOOL, &reconnect); 2518 2519 dtds[0] = &dtd2; 2520 values[0] = &hid_spec_type; 2521 dtds[1] = &dtd_data; 2522 values[1] = (uint8_t *) hid_spec; 2523 leng[0] = 0; 2524 leng[1] = sizeof(hid_spec); 2525 hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2); 2526 hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst); 2527 sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2); 2528 2529 for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) { 2530 dtds2[i] = &dtd; 2531 values2[i] = &hid_attr_lang[i]; 2532 } 2533 2534 lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2); 2535 lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst); 2536 sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2); 2537 2538 sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, 2539 SDP_BOOL, &sdp_disable); 2540 2541 sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER, 2542 SDP_BOOL, &battery); 2543 2544 sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP, 2545 SDP_BOOL, &remote_wakeup); 2546 2547 sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION, 2548 SDP_UINT16, &profile_version); 2549 2550 sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT, 2551 SDP_UINT16, &superv_timeout); 2552 2553 sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE, 2554 SDP_BOOL, &norm_connect); 2555 2556 sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE, 2557 SDP_BOOL, &boot_device); 2558 2559 if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { 2560 printf("Service Record registration failed\n"); 2561 return -1; 2562 } 2563 2564 printf("Wii-Mote service registered\n"); 2565 2566 return 0; 2567 } 2568 2569 static int add_cip(sdp_session_t *session, svc_info_t *si) 2570 { 2571 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2572 uuid_t root_uuid, l2cap, cmtp, cip; 2573 sdp_profile_desc_t profile[1]; 2574 sdp_list_t *aproto, *proto[2]; 2575 sdp_record_t record; 2576 uint16_t psm = si->psm ? si->psm : 0x1001; 2577 uint8_t netid = si->network ? si->network : 0x02; // 0x02 = ISDN, 0x03 = GSM 2578 sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); 2579 int ret = 0; 2580 2581 memset(&record, 0, sizeof(sdp_record_t)); 2582 record.handle = si->handle; 2583 2584 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2585 root = sdp_list_append(0, &root_uuid); 2586 sdp_set_browse_groups(&record, root); 2587 2588 sdp_uuid16_create(&cip, CIP_SVCLASS_ID); 2589 svclass_id = sdp_list_append(0, &cip); 2590 sdp_set_service_classes(&record, svclass_id); 2591 2592 sdp_uuid16_create(&profile[0].uuid, CIP_PROFILE_ID); 2593 profile[0].version = 0x0100; 2594 pfseq = sdp_list_append(0, &profile[0]); 2595 sdp_set_profile_descs(&record, pfseq); 2596 2597 sdp_uuid16_create(&l2cap, L2CAP_UUID); 2598 proto[0] = sdp_list_append(0, &l2cap); 2599 apseq = sdp_list_append(0, proto[0]); 2600 proto[0] = sdp_list_append(proto[0], sdp_data_alloc(SDP_UINT16, &psm)); 2601 apseq = sdp_list_append(0, proto[0]); 2602 2603 sdp_uuid16_create(&cmtp, CMTP_UUID); 2604 proto[1] = sdp_list_append(0, &cmtp); 2605 apseq = sdp_list_append(apseq, proto[1]); 2606 2607 aproto = sdp_list_append(0, apseq); 2608 sdp_set_access_protos(&record, aproto); 2609 2610 sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); 2611 2612 sdp_set_info_attr(&record, "Common ISDN Access", 0, 0); 2613 2614 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2615 printf("Service Record registration failed\n"); 2616 ret = -1; 2617 goto end; 2618 } 2619 2620 printf("CIP service registered\n"); 2621 2622 end: 2623 sdp_list_free(proto[0], 0); 2624 sdp_list_free(proto[1], 0); 2625 sdp_list_free(apseq, 0); 2626 sdp_list_free(aproto, 0); 2627 sdp_data_free(network); 2628 2629 return ret; 2630 } 2631 2632 static int add_ctp(sdp_session_t *session, svc_info_t *si) 2633 { 2634 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2635 uuid_t root_uuid, l2cap, tcsbin, ctp; 2636 sdp_profile_desc_t profile[1]; 2637 sdp_list_t *aproto, *proto[2]; 2638 sdp_record_t record; 2639 uint8_t netid = si->network ? si->network : 0x02; // 0x01-0x07 cf. p120 profile document 2640 sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); 2641 int ret = 0; 2642 2643 memset(&record, 0, sizeof(sdp_record_t)); 2644 record.handle = si->handle; 2645 2646 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2647 root = sdp_list_append(0, &root_uuid); 2648 sdp_set_browse_groups(&record, root); 2649 2650 sdp_uuid16_create(&ctp, CORDLESS_TELEPHONY_SVCLASS_ID); 2651 svclass_id = sdp_list_append(0, &ctp); 2652 sdp_set_service_classes(&record, svclass_id); 2653 2654 sdp_uuid16_create(&profile[0].uuid, CORDLESS_TELEPHONY_PROFILE_ID); 2655 profile[0].version = 0x0100; 2656 pfseq = sdp_list_append(0, &profile[0]); 2657 sdp_set_profile_descs(&record, pfseq); 2658 2659 sdp_uuid16_create(&l2cap, L2CAP_UUID); 2660 proto[0] = sdp_list_append(0, &l2cap); 2661 apseq = sdp_list_append(0, proto[0]); 2662 2663 sdp_uuid16_create(&tcsbin, TCS_BIN_UUID); 2664 proto[1] = sdp_list_append(0, &tcsbin); 2665 apseq = sdp_list_append(apseq, proto[1]); 2666 2667 aproto = sdp_list_append(0, apseq); 2668 sdp_set_access_protos(&record, aproto); 2669 2670 sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); 2671 2672 sdp_set_info_attr(&record, "Cordless Telephony", 0, 0); 2673 2674 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2675 printf("Service Record registration failed\n"); 2676 ret = -1; 2677 goto end; 2678 } 2679 2680 printf("CTP service registered\n"); 2681 2682 end: 2683 sdp_list_free(proto[0], 0); 2684 sdp_list_free(proto[1], 0); 2685 sdp_list_free(apseq, 0); 2686 sdp_list_free(aproto, 0); 2687 sdp_data_free(network); 2688 2689 return ret; 2690 } 2691 2692 static int add_a2source(sdp_session_t *session, svc_info_t *si) 2693 { 2694 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2695 uuid_t root_uuid, l2cap, avdtp, a2src; 2696 sdp_profile_desc_t profile[1]; 2697 sdp_list_t *aproto, *proto[2]; 2698 sdp_record_t record; 2699 sdp_data_t *psm, *version; 2700 uint16_t lp = 0x0019, ver = 0x0100; 2701 int ret = 0; 2702 2703 memset(&record, 0, sizeof(sdp_record_t)); 2704 record.handle = si->handle; 2705 2706 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2707 root = sdp_list_append(0, &root_uuid); 2708 sdp_set_browse_groups(&record, root); 2709 2710 sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID); 2711 svclass_id = sdp_list_append(0, &a2src); 2712 sdp_set_service_classes(&record, svclass_id); 2713 2714 sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID); 2715 profile[0].version = 0x0100; 2716 pfseq = sdp_list_append(0, &profile[0]); 2717 sdp_set_profile_descs(&record, pfseq); 2718 2719 sdp_uuid16_create(&l2cap, L2CAP_UUID); 2720 proto[0] = sdp_list_append(0, &l2cap); 2721 psm = sdp_data_alloc(SDP_UINT16, &lp); 2722 proto[0] = sdp_list_append(proto[0], psm); 2723 apseq = sdp_list_append(0, proto[0]); 2724 2725 sdp_uuid16_create(&avdtp, AVDTP_UUID); 2726 proto[1] = sdp_list_append(0, &avdtp); 2727 version = sdp_data_alloc(SDP_UINT16, &ver); 2728 proto[1] = sdp_list_append(proto[1], version); 2729 apseq = sdp_list_append(apseq, proto[1]); 2730 2731 aproto = sdp_list_append(0, apseq); 2732 sdp_set_access_protos(&record, aproto); 2733 2734 sdp_set_info_attr(&record, "Audio Source", 0, 0); 2735 2736 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2737 printf("Service Record registration failed\n"); 2738 ret = -1; 2739 goto done; 2740 } 2741 2742 printf("Audio source service registered\n"); 2743 2744 done: 2745 sdp_list_free(proto[0], 0); 2746 sdp_list_free(proto[1], 0); 2747 sdp_list_free(apseq, 0); 2748 sdp_list_free(aproto, 0); 2749 2750 return ret; 2751 } 2752 2753 static int add_a2sink(sdp_session_t *session, svc_info_t *si) 2754 { 2755 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2756 uuid_t root_uuid, l2cap, avdtp, a2snk; 2757 sdp_profile_desc_t profile[1]; 2758 sdp_list_t *aproto, *proto[2]; 2759 sdp_record_t record; 2760 sdp_data_t *psm, *version; 2761 uint16_t lp = 0x0019, ver = 0x0100; 2762 int ret = 0; 2763 2764 memset(&record, 0, sizeof(sdp_record_t)); 2765 record.handle = si->handle; 2766 2767 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2768 root = sdp_list_append(0, &root_uuid); 2769 sdp_set_browse_groups(&record, root); 2770 2771 sdp_uuid16_create(&a2snk, AUDIO_SINK_SVCLASS_ID); 2772 svclass_id = sdp_list_append(0, &a2snk); 2773 sdp_set_service_classes(&record, svclass_id); 2774 2775 sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID); 2776 profile[0].version = 0x0100; 2777 pfseq = sdp_list_append(0, &profile[0]); 2778 sdp_set_profile_descs(&record, pfseq); 2779 2780 sdp_uuid16_create(&l2cap, L2CAP_UUID); 2781 proto[0] = sdp_list_append(0, &l2cap); 2782 psm = sdp_data_alloc(SDP_UINT16, &lp); 2783 proto[0] = sdp_list_append(proto[0], psm); 2784 apseq = sdp_list_append(0, proto[0]); 2785 2786 sdp_uuid16_create(&avdtp, AVDTP_UUID); 2787 proto[1] = sdp_list_append(0, &avdtp); 2788 version = sdp_data_alloc(SDP_UINT16, &ver); 2789 proto[1] = sdp_list_append(proto[1], version); 2790 apseq = sdp_list_append(apseq, proto[1]); 2791 2792 aproto = sdp_list_append(0, apseq); 2793 sdp_set_access_protos(&record, aproto); 2794 2795 sdp_set_info_attr(&record, "Audio Sink", 0, 0); 2796 2797 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2798 printf("Service Record registration failed\n"); 2799 ret = -1; 2800 goto done; 2801 } 2802 2803 printf("Audio sink service registered\n"); 2804 2805 done: 2806 sdp_list_free(proto[0], 0); 2807 sdp_list_free(proto[1], 0); 2808 sdp_list_free(apseq, 0); 2809 sdp_list_free(aproto, 0); 2810 2811 return ret; 2812 } 2813 2814 static int add_avrct(sdp_session_t *session, svc_info_t *si) 2815 { 2816 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2817 uuid_t root_uuid, l2cap, avctp, avrct; 2818 sdp_profile_desc_t profile[1]; 2819 sdp_list_t *aproto, *proto[2]; 2820 sdp_record_t record; 2821 sdp_data_t *psm, *version, *features; 2822 uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f; 2823 int ret = 0; 2824 2825 memset(&record, 0, sizeof(sdp_record_t)); 2826 record.handle = si->handle; 2827 2828 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2829 root = sdp_list_append(0, &root_uuid); 2830 sdp_set_browse_groups(&record, root); 2831 2832 sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID); 2833 svclass_id = sdp_list_append(0, &avrct); 2834 sdp_set_service_classes(&record, svclass_id); 2835 2836 sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID); 2837 profile[0].version = 0x0100; 2838 pfseq = sdp_list_append(0, &profile[0]); 2839 sdp_set_profile_descs(&record, pfseq); 2840 2841 sdp_uuid16_create(&l2cap, L2CAP_UUID); 2842 proto[0] = sdp_list_append(0, &l2cap); 2843 psm = sdp_data_alloc(SDP_UINT16, &lp); 2844 proto[0] = sdp_list_append(proto[0], psm); 2845 apseq = sdp_list_append(0, proto[0]); 2846 2847 sdp_uuid16_create(&avctp, AVCTP_UUID); 2848 proto[1] = sdp_list_append(0, &avctp); 2849 version = sdp_data_alloc(SDP_UINT16, &ver); 2850 proto[1] = sdp_list_append(proto[1], version); 2851 apseq = sdp_list_append(apseq, proto[1]); 2852 2853 aproto = sdp_list_append(0, apseq); 2854 sdp_set_access_protos(&record, aproto); 2855 2856 features = sdp_data_alloc(SDP_UINT16, &feat); 2857 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); 2858 2859 sdp_set_info_attr(&record, "AVRCP CT", 0, 0); 2860 2861 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2862 printf("Service Record registration failed\n"); 2863 ret = -1; 2864 goto done; 2865 } 2866 2867 printf("Remote control service registered\n"); 2868 2869 done: 2870 sdp_list_free(proto[0], 0); 2871 sdp_list_free(proto[1], 0); 2872 sdp_list_free(apseq, 0); 2873 sdp_list_free(aproto, 0); 2874 2875 return ret; 2876 } 2877 2878 static int add_avrtg(sdp_session_t *session, svc_info_t *si) 2879 { 2880 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 2881 uuid_t root_uuid, l2cap, avctp, avrtg; 2882 sdp_profile_desc_t profile[1]; 2883 sdp_list_t *aproto, *proto[2]; 2884 sdp_record_t record; 2885 sdp_data_t *psm, *version, *features; 2886 uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f; 2887 int ret = 0; 2888 2889 memset(&record, 0, sizeof(sdp_record_t)); 2890 record.handle = si->handle; 2891 2892 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2893 root = sdp_list_append(0, &root_uuid); 2894 sdp_set_browse_groups(&record, root); 2895 2896 sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID); 2897 svclass_id = sdp_list_append(0, &avrtg); 2898 sdp_set_service_classes(&record, svclass_id); 2899 2900 sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID); 2901 profile[0].version = 0x0100; 2902 pfseq = sdp_list_append(0, &profile[0]); 2903 sdp_set_profile_descs(&record, pfseq); 2904 2905 sdp_uuid16_create(&l2cap, L2CAP_UUID); 2906 proto[0] = sdp_list_append(0, &l2cap); 2907 psm = sdp_data_alloc(SDP_UINT16, &lp); 2908 proto[0] = sdp_list_append(proto[0], psm); 2909 apseq = sdp_list_append(0, proto[0]); 2910 2911 sdp_uuid16_create(&avctp, AVCTP_UUID); 2912 proto[1] = sdp_list_append(0, &avctp); 2913 version = sdp_data_alloc(SDP_UINT16, &ver); 2914 proto[1] = sdp_list_append(proto[1], version); 2915 apseq = sdp_list_append(apseq, proto[1]); 2916 2917 aproto = sdp_list_append(0, apseq); 2918 sdp_set_access_protos(&record, aproto); 2919 2920 features = sdp_data_alloc(SDP_UINT16, &feat); 2921 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); 2922 2923 sdp_set_info_attr(&record, "AVRCP TG", 0, 0); 2924 2925 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2926 printf("Service Record registration failed\n"); 2927 ret = -1; 2928 goto done; 2929 } 2930 2931 printf("Remote target service registered\n"); 2932 2933 done: 2934 sdp_list_free(proto[0], 0); 2935 sdp_list_free(proto[1], 0); 2936 sdp_list_free(apseq, 0); 2937 sdp_list_free(aproto, 0); 2938 2939 return ret; 2940 } 2941 2942 static int add_udi_ue(sdp_session_t *session, svc_info_t *si) 2943 { 2944 sdp_record_t record; 2945 sdp_list_t *root, *svclass, *proto; 2946 uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; 2947 uint8_t channel = si->channel ? si->channel: 18; 2948 2949 memset(&record, 0, sizeof(record)); 2950 record.handle = si->handle; 2951 2952 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2953 root = sdp_list_append(NULL, &root_uuid); 2954 sdp_set_browse_groups(&record, root); 2955 sdp_list_free(root, NULL); 2956 2957 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 2958 proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); 2959 2960 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 2961 proto = sdp_list_append(proto, sdp_list_append( 2962 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); 2963 2964 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 2965 2966 sdp_uuid16_create(&svclass_uuid, UDI_MT_SVCLASS_ID); 2967 svclass = sdp_list_append(NULL, &svclass_uuid); 2968 sdp_set_service_classes(&record, svclass); 2969 sdp_list_free(svclass, NULL); 2970 2971 sdp_set_info_attr(&record, "UDI UE", NULL, NULL); 2972 2973 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 2974 printf("Service Record registration failed\n"); 2975 return -1; 2976 } 2977 2978 printf("UDI UE service registered\n"); 2979 2980 return 0; 2981 } 2982 2983 static int add_udi_te(sdp_session_t *session, svc_info_t *si) 2984 { 2985 sdp_record_t record; 2986 sdp_list_t *root, *svclass, *proto; 2987 uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; 2988 uint8_t channel = si->channel ? si->channel: 19; 2989 2990 memset(&record, 0, sizeof(record)); 2991 record.handle = si->handle; 2992 2993 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 2994 root = sdp_list_append(NULL, &root_uuid); 2995 sdp_set_browse_groups(&record, root); 2996 sdp_list_free(root, NULL); 2997 2998 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 2999 proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); 3000 3001 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 3002 proto = sdp_list_append(proto, sdp_list_append( 3003 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); 3004 3005 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 3006 3007 sdp_uuid16_create(&svclass_uuid, UDI_TA_SVCLASS_ID); 3008 svclass = sdp_list_append(NULL, &svclass_uuid); 3009 sdp_set_service_classes(&record, svclass); 3010 sdp_list_free(svclass, NULL); 3011 3012 sdp_set_info_attr(&record, "UDI TE", NULL, NULL); 3013 3014 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3015 printf("Service Record registration failed\n"); 3016 return -1; 3017 } 3018 3019 printf("UDI TE service registered\n"); 3020 3021 return 0; 3022 } 3023 3024 static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0, 3025 0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 }; 3026 3027 static int add_sr1(sdp_session_t *session, svc_info_t *si) 3028 { 3029 sdp_record_t record; 3030 sdp_list_t *root, *svclass; 3031 uuid_t root_uuid, svclass_uuid; 3032 3033 memset(&record, 0, sizeof(record)); 3034 record.handle = si->handle; 3035 3036 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3037 root = sdp_list_append(NULL, &root_uuid); 3038 sdp_set_browse_groups(&record, root); 3039 3040 sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid); 3041 svclass = sdp_list_append(NULL, &svclass_uuid); 3042 sdp_set_service_classes(&record, svclass); 3043 3044 sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL); 3045 3046 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3047 printf("Service Record registration failed\n"); 3048 return -1; 3049 } 3050 3051 printf("Toshiba Speech Recognition SR-1 service record registered\n"); 3052 3053 return 0; 3054 } 3055 3056 static unsigned char syncmls_uuid[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 3057 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 }; 3058 3059 static unsigned char syncmlc_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 3060 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 }; 3061 3062 static int add_syncml(sdp_session_t *session, svc_info_t *si) 3063 { 3064 sdp_record_t record; 3065 sdp_list_t *root, *svclass, *proto; 3066 uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; 3067 uint8_t channel = si->channel ? si->channel: 15; 3068 3069 memset(&record, 0, sizeof(record)); 3070 record.handle = si->handle; 3071 3072 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3073 root = sdp_list_append(NULL, &root_uuid); 3074 sdp_set_browse_groups(&record, root); 3075 3076 sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid); 3077 svclass = sdp_list_append(NULL, &svclass_uuid); 3078 sdp_set_service_classes(&record, svclass); 3079 3080 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 3081 proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); 3082 3083 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 3084 proto = sdp_list_append(proto, sdp_list_append( 3085 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); 3086 3087 sdp_uuid16_create(&obex_uuid, OBEX_UUID); 3088 proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid)); 3089 3090 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 3091 3092 sdp_set_info_attr(&record, "SyncML Client", NULL, NULL); 3093 3094 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3095 printf("Service Record registration failed\n"); 3096 return -1; 3097 } 3098 3099 printf("SyncML Client service record registered\n"); 3100 3101 return 0; 3102 } 3103 3104 static unsigned char async_uuid[] = { 0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62, 3105 0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C }; 3106 3107 static int add_activesync(sdp_session_t *session, svc_info_t *si) 3108 { 3109 sdp_record_t record; 3110 sdp_list_t *root, *svclass, *proto; 3111 uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; 3112 uint8_t channel = si->channel ? si->channel: 21; 3113 3114 memset(&record, 0, sizeof(record)); 3115 record.handle = si->handle; 3116 3117 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3118 root = sdp_list_append(NULL, &root_uuid); 3119 sdp_set_browse_groups(&record, root); 3120 3121 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 3122 proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); 3123 3124 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 3125 proto = sdp_list_append(proto, sdp_list_append( 3126 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); 3127 3128 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 3129 3130 sdp_uuid128_create(&svclass_uuid, (void *) async_uuid); 3131 svclass = sdp_list_append(NULL, &svclass_uuid); 3132 sdp_set_service_classes(&record, svclass); 3133 3134 sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL); 3135 3136 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3137 printf("Service Record registration failed\n"); 3138 return -1; 3139 } 3140 3141 printf("ActiveSync service record registered\n"); 3142 3143 return 0; 3144 } 3145 3146 static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5, 3147 0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C }; 3148 3149 static int add_hotsync(sdp_session_t *session, svc_info_t *si) 3150 { 3151 sdp_record_t record; 3152 sdp_list_t *root, *svclass, *proto; 3153 uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; 3154 uint8_t channel = si->channel ? si->channel: 22; 3155 3156 memset(&record, 0, sizeof(record)); 3157 record.handle = si->handle; 3158 3159 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3160 root = sdp_list_append(NULL, &root_uuid); 3161 sdp_set_browse_groups(&record, root); 3162 3163 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 3164 proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); 3165 3166 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 3167 proto = sdp_list_append(proto, sdp_list_append( 3168 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); 3169 3170 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 3171 3172 sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid); 3173 svclass = sdp_list_append(NULL, &svclass_uuid); 3174 sdp_set_service_classes(&record, svclass); 3175 3176 sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL); 3177 3178 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3179 printf("Service Record registration failed\n"); 3180 return -1; 3181 } 3182 3183 printf("HotSync service record registered\n"); 3184 3185 return 0; 3186 } 3187 3188 static unsigned char palmos_uuid[] = { 0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51, 3189 0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 }; 3190 3191 static int add_palmos(sdp_session_t *session, svc_info_t *si) 3192 { 3193 sdp_record_t record; 3194 sdp_list_t *root, *svclass; 3195 uuid_t root_uuid, svclass_uuid; 3196 3197 memset(&record, 0, sizeof(record)); 3198 record.handle = si->handle; 3199 3200 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3201 root = sdp_list_append(NULL, &root_uuid); 3202 sdp_set_browse_groups(&record, root); 3203 3204 sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid); 3205 svclass = sdp_list_append(NULL, &svclass_uuid); 3206 sdp_set_service_classes(&record, svclass); 3207 3208 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3209 printf("Service Record registration failed\n"); 3210 return -1; 3211 } 3212 3213 printf("PalmOS service record registered\n"); 3214 3215 return 0; 3216 } 3217 3218 static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00, 3219 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; 3220 3221 static int add_nokiaid(sdp_session_t *session, svc_info_t *si) 3222 { 3223 sdp_record_t record; 3224 sdp_list_t *root, *svclass; 3225 uuid_t root_uuid, svclass_uuid; 3226 uint16_t verid = 0x005f; 3227 sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid); 3228 3229 memset(&record, 0, sizeof(record)); 3230 record.handle = si->handle; 3231 3232 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3233 root = sdp_list_append(NULL, &root_uuid); 3234 sdp_set_browse_groups(&record, root); 3235 3236 sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid); 3237 svclass = sdp_list_append(NULL, &svclass_uuid); 3238 sdp_set_service_classes(&record, svclass); 3239 3240 sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version); 3241 3242 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3243 printf("Service Record registration failed\n"); 3244 sdp_data_free(version); 3245 return -1; 3246 } 3247 3248 printf("Nokia ID service record registered\n"); 3249 3250 return 0; 3251 } 3252 3253 static unsigned char pcsuite_uuid[] = { 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00, 3254 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; 3255 3256 static int add_pcsuite(sdp_session_t *session, svc_info_t *si) 3257 { 3258 sdp_record_t record; 3259 sdp_list_t *root, *svclass, *proto; 3260 uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; 3261 uint8_t channel = si->channel ? si->channel: 14; 3262 3263 memset(&record, 0, sizeof(record)); 3264 record.handle = si->handle; 3265 3266 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3267 root = sdp_list_append(NULL, &root_uuid); 3268 sdp_set_browse_groups(&record, root); 3269 3270 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 3271 proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); 3272 3273 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 3274 proto = sdp_list_append(proto, sdp_list_append( 3275 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); 3276 3277 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 3278 3279 sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid); 3280 svclass = sdp_list_append(NULL, &svclass_uuid); 3281 sdp_set_service_classes(&record, svclass); 3282 3283 sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL); 3284 3285 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3286 printf("Service Record registration failed\n"); 3287 return -1; 3288 } 3289 3290 printf("Nokia PC Suite service registered\n"); 3291 3292 return 0; 3293 } 3294 3295 static unsigned char nftp_uuid[] = { 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00, 3296 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; 3297 3298 static unsigned char nsyncml_uuid[] = { 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x10, 0x00, 3299 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; 3300 3301 static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00, 3302 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; 3303 3304 static unsigned char apple_uuid[] = { 0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90, 3305 0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 }; 3306 3307 static int add_apple(sdp_session_t *session, svc_info_t *si) 3308 { 3309 sdp_record_t record; 3310 sdp_list_t *root; 3311 uuid_t root_uuid; 3312 uint32_t attr783 = 0x00000000; 3313 uint32_t attr785 = 0x00000002; 3314 uint16_t attr786 = 0x1234; 3315 3316 memset(&record, 0, sizeof(record)); 3317 record.handle = si->handle; 3318 3319 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3320 root = sdp_list_append(NULL, &root_uuid); 3321 sdp_set_browse_groups(&record, root); 3322 3323 sdp_attr_add_new(&record, 0x0780, SDP_UUID128, (void *) apple_uuid); 3324 sdp_attr_add_new(&record, 0x0781, SDP_TEXT_STR8, (void *) "Macmini"); 3325 sdp_attr_add_new(&record, 0x0782, SDP_TEXT_STR8, (void *) "PowerMac10,1"); 3326 sdp_attr_add_new(&record, 0x0783, SDP_UINT32, (void *) &attr783); 3327 sdp_attr_add_new(&record, 0x0784, SDP_TEXT_STR8, (void *) "1.6.6f22"); 3328 sdp_attr_add_new(&record, 0x0785, SDP_UINT32, (void *) &attr785); 3329 sdp_attr_add_new(&record, 0x0786, SDP_UUID16, (void *) &attr786); 3330 3331 sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL); 3332 3333 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3334 printf("Service Record registration failed\n"); 3335 return -1; 3336 } 3337 3338 printf("Apple attribute service registered\n"); 3339 3340 return 0; 3341 } 3342 3343 static int add_isync(sdp_session_t *session, svc_info_t *si) 3344 { 3345 sdp_record_t record; 3346 sdp_list_t *root, *svclass, *proto; 3347 uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid; 3348 uint8_t channel = si->channel ? si->channel : 16; 3349 3350 memset(&record, 0, sizeof(record)); 3351 record.handle = si->handle; 3352 3353 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3354 root = sdp_list_append(NULL, &root_uuid); 3355 sdp_set_browse_groups(&record, root); 3356 3357 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 3358 proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); 3359 3360 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 3361 proto = sdp_list_append(proto, sdp_list_append( 3362 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); 3363 3364 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 3365 3366 sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID); 3367 svclass = sdp_list_append(NULL, &serial_uuid); 3368 3369 sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID); 3370 svclass = sdp_list_append(svclass, &svclass_uuid); 3371 3372 sdp_set_service_classes(&record, svclass); 3373 3374 sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd."); 3375 3376 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3377 printf("Service Record registration failed\n"); 3378 return -1; 3379 } 3380 3381 printf("Apple iSync service registered\n"); 3382 3383 return 0; 3384 } 3385 3386 static int add_semchla(sdp_session_t *session, svc_info_t *si) 3387 { 3388 sdp_record_t record; 3389 sdp_profile_desc_t profile; 3390 sdp_list_t *root, *svclass, *proto, *profiles; 3391 uuid_t root_uuid, service_uuid, l2cap_uuid, semchla_uuid; 3392 uint16_t psm = 0xf0f9; 3393 3394 memset(&record, 0, sizeof(record)); 3395 record.handle = si->handle; 3396 3397 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3398 root = sdp_list_append(NULL, &root_uuid); 3399 sdp_set_browse_groups(&record, root); 3400 3401 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 3402 proto = sdp_list_append(NULL, sdp_list_append( 3403 sdp_list_append(NULL, &l2cap_uuid), sdp_data_alloc(SDP_UINT16, &psm))); 3404 3405 sdp_uuid32_create(&semchla_uuid, 0x8e770300); 3406 proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid)); 3407 3408 sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); 3409 3410 sdp_uuid32_create(&service_uuid, 0x8e771301); 3411 svclass = sdp_list_append(NULL, &service_uuid); 3412 3413 sdp_set_service_classes(&record, svclass); 3414 3415 sdp_uuid32_create(&profile.uuid, 0x8e771302); // Headset 3416 //sdp_uuid32_create(&profile.uuid, 0x8e771303); // Phone 3417 profile.version = 0x0100; 3418 profiles = sdp_list_append(NULL, &profile); 3419 sdp_set_profile_descs(&record, profiles); 3420 3421 sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL); 3422 3423 if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { 3424 printf("Service Record registration failed\n"); 3425 return -1; 3426 } 3427 3428 /* SEMC High Level Authentication */ 3429 printf("SEMC HLA service registered\n"); 3430 3431 return 0; 3432 } 3433 3434 struct { 3435 char *name; 3436 uint32_t class; 3437 int (*add)(sdp_session_t *sess, svc_info_t *si); 3438 unsigned char *uuid; 3439 } service[] = { 3440 { "DID", PNP_INFO_SVCLASS_ID, NULL, }, 3441 3442 { "SP", SERIAL_PORT_SVCLASS_ID, add_sp }, 3443 { "DUN", DIALUP_NET_SVCLASS_ID, add_dun }, 3444 { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan }, 3445 { "FAX", FAX_SVCLASS_ID, add_fax }, 3446 { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush }, 3447 { "FTP", OBEX_FILETRANS_SVCLASS_ID, add_ftp }, 3448 { "PRINT", DIRECT_PRINTING_SVCLASS_ID, add_directprint }, 3449 3450 { "HS", HEADSET_SVCLASS_ID, add_headset }, 3451 { "HSAG", HEADSET_AGW_SVCLASS_ID, add_headset_ag }, 3452 { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, 3453 { "HFAG", HANDSFREE_AGW_SVCLASS_ID, add_handsfree_ag}, 3454 { "SAP", SAP_SVCLASS_ID, add_simaccess }, 3455 { "PBAP", PBAP_SVCLASS_ID, add_pbap, }, 3456 3457 { "NAP", NAP_SVCLASS_ID, add_nap }, 3458 { "GN", GN_SVCLASS_ID, add_gn }, 3459 { "PANU", PANU_SVCLASS_ID, add_panu }, 3460 3461 { "HCRP", HCR_SVCLASS_ID, NULL }, 3462 { "HID", HID_SVCLASS_ID, NULL }, 3463 { "KEYB", HID_SVCLASS_ID, add_hid_keyb }, 3464 { "WIIMOTE", HID_SVCLASS_ID, add_hid_wiimote }, 3465 { "CIP", CIP_SVCLASS_ID, add_cip }, 3466 { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, 3467 3468 { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source }, 3469 { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink }, 3470 { "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct }, 3471 { "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg }, 3472 3473 { "UDIUE", UDI_MT_SVCLASS_ID, add_udi_ue }, 3474 { "UDITE", UDI_TA_SVCLASS_ID, add_udi_te }, 3475 3476 { "SEMCHLA", 0x8e771301, add_semchla }, 3477 3478 { "SR1", 0, add_sr1, sr1_uuid }, 3479 { "SYNCML", 0, add_syncml, syncmlc_uuid }, 3480 { "SYNCMLSERV", 0, NULL, syncmls_uuid }, 3481 { "ACTIVESYNC", 0, add_activesync, async_uuid }, 3482 { "HOTSYNC", 0, add_hotsync, hotsync_uuid }, 3483 { "PALMOS", 0, add_palmos, palmos_uuid }, 3484 { "NOKID", 0, add_nokiaid, nokid_uuid }, 3485 { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, 3486 { "NFTP", 0, NULL, nftp_uuid }, 3487 { "NSYNCML", 0, NULL, nsyncml_uuid }, 3488 { "NGAGE", 0, NULL, ngage_uuid }, 3489 { "APPLE", 0, add_apple, apple_uuid }, 3490 3491 { "ISYNC", APPLE_AGENT_SVCLASS_ID, add_isync, }, 3492 3493 { 0 } 3494 }; 3495 3496 /* Add local service */ 3497 static int add_service(bdaddr_t *bdaddr, svc_info_t *si) 3498 { 3499 sdp_session_t *sess; 3500 int i, ret = -1; 3501 3502 if (!si->name) 3503 return -1; 3504 3505 sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); 3506 if (!sess) 3507 return -1; 3508 3509 for (i = 0; service[i].name; i++) 3510 if (!strcasecmp(service[i].name, si->name)) { 3511 if (service[i].add) 3512 ret = service[i].add(sess, si); 3513 goto done; 3514 } 3515 3516 printf("Unknown service name: %s\n", si->name); 3517 3518 done: 3519 free(si->name); 3520 sdp_close(sess); 3521 3522 return ret; 3523 } 3524 3525 static struct option add_options[] = { 3526 { "help", 0, 0, 'h' }, 3527 { "handle", 1, 0, 'r' }, 3528 { "psm", 1, 0, 'p' }, 3529 { "channel", 1, 0, 'c' }, 3530 { "network", 1, 0, 'n' }, 3531 { 0, 0, 0, 0 } 3532 }; 3533 3534 static const char *add_help = 3535 "Usage:\n" 3536 "\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n"; 3537 3538 static int cmd_add(int argc, char **argv) 3539 { 3540 svc_info_t si; 3541 int opt; 3542 3543 memset(&si, 0, sizeof(si)); 3544 si.handle = 0xffffffff; 3545 3546 for_each_opt(opt, add_options, 0) { 3547 switch (opt) { 3548 case 'r': 3549 if (strncasecmp(optarg, "0x", 2)) 3550 si.handle = atoi(optarg); 3551 else 3552 si.handle = strtol(optarg + 2, NULL, 16); 3553 break; 3554 case 'p': 3555 if (strncasecmp(optarg, "0x", 2)) 3556 si.psm = atoi(optarg); 3557 else 3558 si.psm = strtol(optarg + 2, NULL, 16); 3559 break; 3560 case 'c': 3561 if (strncasecmp(optarg, "0x", 2)) 3562 si.channel = atoi(optarg); 3563 else 3564 si.channel = strtol(optarg + 2, NULL, 16); 3565 break; 3566 case 'n': 3567 if (strncasecmp(optarg, "0x", 2)) 3568 si.network = atoi(optarg); 3569 else 3570 si.network = strtol(optarg + 2, NULL, 16); 3571 break; 3572 default: 3573 printf("%s", add_help); 3574 return -1; 3575 } 3576 } 3577 3578 argc -= optind; 3579 argv += optind; 3580 3581 if (argc < 1) { 3582 printf("%s", add_help); 3583 return -1; 3584 } 3585 3586 si.name = strdup(argv[0]); 3587 3588 return add_service(0, &si); 3589 } 3590 3591 /* Delete local service */ 3592 static int del_service(bdaddr_t *bdaddr, void *arg) 3593 { 3594 uint32_t handle, range = 0x0000ffff; 3595 sdp_list_t *attr; 3596 sdp_session_t *sess; 3597 sdp_record_t *rec; 3598 3599 if (!arg) { 3600 printf("Record handle was not specified.\n"); 3601 return -1; 3602 } 3603 3604 sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); 3605 if (!sess) { 3606 printf("No local SDP server!\n"); 3607 return -1; 3608 } 3609 3610 handle = strtoul((char *)arg, 0, 16); 3611 attr = sdp_list_append(0, &range); 3612 rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr); 3613 sdp_list_free(attr, 0); 3614 3615 if (!rec) { 3616 printf("Service Record not found.\n"); 3617 sdp_close(sess); 3618 return -1; 3619 } 3620 3621 if (sdp_device_record_unregister(sess, &interface, rec)) { 3622 printf("Failed to unregister service record: %s\n", strerror(errno)); 3623 sdp_close(sess); 3624 return -1; 3625 } 3626 3627 printf("Service Record deleted.\n"); 3628 sdp_close(sess); 3629 3630 return 0; 3631 } 3632 3633 static struct option del_options[] = { 3634 { "help", 0, 0, 'h' }, 3635 { 0, 0, 0, 0 } 3636 }; 3637 3638 static const char *del_help = 3639 "Usage:\n" 3640 "\tdel record_handle\n"; 3641 3642 static int cmd_del(int argc, char **argv) 3643 { 3644 int opt; 3645 3646 for_each_opt(opt, del_options, 0) { 3647 switch (opt) { 3648 default: 3649 printf("%s", del_help); 3650 return -1; 3651 } 3652 } 3653 3654 argc -= optind; 3655 argv += optind; 3656 3657 if (argc < 1) { 3658 printf("%s", del_help); 3659 return -1; 3660 } 3661 3662 return del_service(NULL, argv[0]); 3663 } 3664 3665 /* 3666 * Perform an inquiry and search/browse all peer found. 3667 */ 3668 static void inquiry(handler_t handler, void *arg) 3669 { 3670 inquiry_info ii[20]; 3671 uint8_t count = 0; 3672 int i; 3673 3674 printf("Inquiring ...\n"); 3675 if (sdp_general_inquiry(ii, 20, 8, &count) < 0) { 3676 printf("Inquiry failed\n"); 3677 return; 3678 } 3679 3680 for (i = 0; i < count; i++) 3681 handler(&ii[i].bdaddr, arg); 3682 } 3683 3684 static void doprintf(void *data, const char *str) 3685 { 3686 printf("%s", str); 3687 } 3688 3689 /* 3690 * Search for a specific SDP service 3691 */ 3692 static int do_search(bdaddr_t *bdaddr, struct search_context *context) 3693 { 3694 sdp_list_t *attrid, *search, *seq, *next; 3695 uint32_t range = 0x0000ffff; 3696 char str[20]; 3697 sdp_session_t *sess; 3698 3699 if (!bdaddr) { 3700 inquiry(do_search, context); 3701 return 0; 3702 } 3703 3704 sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); 3705 ba2str(bdaddr, str); 3706 if (!sess) { 3707 printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); 3708 return -1; 3709 } 3710 3711 if (context->view != RAW_VIEW) { 3712 if (context->svc) 3713 printf("Searching for %s on %s ...\n", context->svc, str); 3714 else 3715 printf("Browsing %s ...\n", str); 3716 } 3717 3718 attrid = sdp_list_append(0, &range); 3719 search = sdp_list_append(0, &context->group); 3720 if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) { 3721 printf("Service Search failed: %s\n", strerror(errno)); 3722 sdp_close(sess); 3723 return -1; 3724 } 3725 sdp_list_free(attrid, 0); 3726 sdp_list_free(search, 0); 3727 3728 for (; seq; seq = next) { 3729 sdp_record_t *rec = (sdp_record_t *) seq->data; 3730 struct search_context sub_context; 3731 3732 switch (context->view) { 3733 case DEFAULT_VIEW: 3734 /* Display user friendly form */ 3735 print_service_attr(rec); 3736 printf("\n"); 3737 break; 3738 case TREE_VIEW: 3739 /* Display full tree */ 3740 print_tree_attr(rec); 3741 printf("\n"); 3742 break; 3743 case XML_VIEW: 3744 /* Display raw XML tree */ 3745 convert_sdp_record_to_xml(rec, 0, doprintf); 3746 break; 3747 default: 3748 /* Display raw tree */ 3749 print_raw_attr(rec); 3750 break; 3751 } 3752 3753 if (sdp_get_group_id(rec, &sub_context.group) != -1) { 3754 /* Set the subcontext for browsing the sub tree */ 3755 memcpy(&sub_context, context, sizeof(struct search_context)); 3756 /* Browse the next level down if not done */ 3757 if (sub_context.group.value.uuid16 != context->group.value.uuid16) 3758 do_search(bdaddr, &sub_context); 3759 } 3760 next = seq->next; 3761 free(seq); 3762 sdp_record_free(rec); 3763 } 3764 3765 sdp_close(sess); 3766 return 0; 3767 } 3768 3769 static struct option browse_options[] = { 3770 { "help", 0, 0, 'h' }, 3771 { "tree", 0, 0, 't' }, 3772 { "raw", 0, 0, 'r' }, 3773 { "xml", 0, 0, 'x' }, 3774 { "uuid", 1, 0, 'u' }, 3775 { "l2cap", 0, 0, 'l' }, 3776 { 0, 0, 0, 0 } 3777 }; 3778 3779 static const char *browse_help = 3780 "Usage:\n" 3781 "\tbrowse [--tree] [--raw] [--xml] [--uuid uuid] [--l2cap] [bdaddr]\n"; 3782 3783 /* 3784 * Browse the full SDP database (i.e. list all services starting from the 3785 * root/top-level). 3786 */ 3787 static int cmd_browse(int argc, char **argv) 3788 { 3789 struct search_context context; 3790 int opt, num; 3791 3792 /* Initialise context */ 3793 memset(&context, '\0', sizeof(struct search_context)); 3794 /* We want to browse the top-level/root */ 3795 sdp_uuid16_create(&context.group, PUBLIC_BROWSE_GROUP); 3796 3797 for_each_opt(opt, browse_options, 0) { 3798 switch (opt) { 3799 case 't': 3800 context.view = TREE_VIEW; 3801 break; 3802 case 'r': 3803 context.view = RAW_VIEW; 3804 break; 3805 case 'x': 3806 context.view = XML_VIEW; 3807 break; 3808 case 'u': 3809 if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) { 3810 printf("Invalid uuid %s\n", optarg); 3811 return -1; 3812 } 3813 sdp_uuid16_create(&context.group, num); 3814 break; 3815 case 'l': 3816 sdp_uuid16_create(&context.group, L2CAP_UUID); 3817 break; 3818 default: 3819 printf("%s", browse_help); 3820 return -1; 3821 } 3822 } 3823 3824 argc -= optind; 3825 argv += optind; 3826 3827 if (argc >= 1) { 3828 bdaddr_t bdaddr; 3829 estr2ba(argv[0], &bdaddr); 3830 return do_search(&bdaddr, &context); 3831 } 3832 3833 return do_search(NULL, &context); 3834 } 3835 3836 static struct option search_options[] = { 3837 { "help", 0, 0, 'h' }, 3838 { "bdaddr", 1, 0, 'b' }, 3839 { "tree", 0, 0, 't' }, 3840 { "raw", 0, 0, 'r' }, 3841 { "xml", 0, 0, 'x' }, 3842 { 0, 0, 0, 0} 3843 }; 3844 3845 static const char *search_help = 3846 "Usage:\n" 3847 "\tsearch [--bdaddr bdaddr] [--tree] [--raw] [--xml] SERVICE\n" 3848 "SERVICE is a name (string) or UUID (0x1002)\n"; 3849 3850 /* 3851 * Search for a specific SDP service 3852 * 3853 * Note : we should support multiple services on the command line : 3854 * sdptool search 0x0100 0x000f 0x1002 3855 * (this would search a service supporting both L2CAP and BNEP directly in 3856 * the top level browse group) 3857 */ 3858 static int cmd_search(int argc, char **argv) 3859 { 3860 struct search_context context; 3861 unsigned char *uuid = NULL; 3862 uint32_t class = 0; 3863 bdaddr_t bdaddr; 3864 int has_addr = 0; 3865 int i; 3866 int opt; 3867 3868 /* Initialise context */ 3869 memset(&context, '\0', sizeof(struct search_context)); 3870 3871 for_each_opt(opt, search_options, 0) { 3872 switch (opt) { 3873 case 'b': 3874 estr2ba(optarg, &bdaddr); 3875 has_addr = 1; 3876 break; 3877 case 't': 3878 context.view = TREE_VIEW; 3879 break; 3880 case 'r': 3881 context.view = RAW_VIEW; 3882 break; 3883 case 'x': 3884 context.view = XML_VIEW; 3885 break; 3886 default: 3887 printf("%s", search_help); 3888 return -1; 3889 } 3890 } 3891 3892 argc -= optind; 3893 argv += optind; 3894 3895 if (argc < 1) { 3896 printf("%s", search_help); 3897 return -1; 3898 } 3899 3900 /* Note : we need to find a way to support search combining 3901 * multiple services */ 3902 context.svc = strdup(argv[0]); 3903 if (!strncasecmp(context.svc, "0x", 2)) { 3904 int num; 3905 /* This is a UUID16, just convert to int */ 3906 sscanf(context.svc + 2, "%X", &num); 3907 class = num; 3908 printf("Class 0x%X\n", class); 3909 } else { 3910 /* Convert class name to an UUID */ 3911 3912 for (i = 0; service[i].name; i++) 3913 if (strcasecmp(context.svc, service[i].name) == 0) { 3914 class = service[i].class; 3915 uuid = service[i].uuid; 3916 break; 3917 } 3918 if (!class && !uuid) { 3919 printf("Unknown service %s\n", context.svc); 3920 return -1; 3921 } 3922 } 3923 3924 if (class) { 3925 if (class & 0xffff0000) 3926 sdp_uuid32_create(&context.group, class); 3927 else { 3928 uint16_t class16 = class & 0xffff; 3929 sdp_uuid16_create(&context.group, class16); 3930 } 3931 } else 3932 sdp_uuid128_create(&context.group, uuid); 3933 3934 if (has_addr) 3935 return do_search(&bdaddr, &context); 3936 3937 return do_search(NULL, &context); 3938 } 3939 3940 /* 3941 * Show how to get a specific SDP record by its handle. 3942 * Not really useful to the user, just show how it can be done... 3943 */ 3944 static int get_service(bdaddr_t *bdaddr, struct search_context *context, int quite) 3945 { 3946 sdp_list_t *attrid; 3947 uint32_t range = 0x0000ffff; 3948 sdp_record_t *rec; 3949 sdp_session_t *session = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); 3950 3951 if (!session) { 3952 char str[20]; 3953 ba2str(bdaddr, str); 3954 printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); 3955 return -1; 3956 } 3957 3958 attrid = sdp_list_append(0, &range); 3959 rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid); 3960 sdp_list_free(attrid, 0); 3961 sdp_close(session); 3962 3963 if (!rec) { 3964 if (!quite) { 3965 printf("Service get request failed.\n"); 3966 return -1; 3967 } else 3968 return 0; 3969 } 3970 3971 switch (context->view) { 3972 case DEFAULT_VIEW: 3973 /* Display user friendly form */ 3974 print_service_attr(rec); 3975 printf("\n"); 3976 break; 3977 case TREE_VIEW: 3978 /* Display full tree */ 3979 print_tree_attr(rec); 3980 printf("\n"); 3981 break; 3982 case XML_VIEW: 3983 /* Display raw XML tree */ 3984 convert_sdp_record_to_xml(rec, 0, doprintf); 3985 break; 3986 default: 3987 /* Display raw tree */ 3988 print_raw_attr(rec); 3989 break; 3990 } 3991 3992 sdp_record_free(rec); 3993 return 0; 3994 } 3995 3996 static struct option records_options[] = { 3997 { "help", 0, 0, 'h' }, 3998 { "tree", 0, 0, 't' }, 3999 { "raw", 0, 0, 'r' }, 4000 { "xml", 0, 0, 'x' }, 4001 { 0, 0, 0, 0 } 4002 }; 4003 4004 static const char *records_help = 4005 "Usage:\n" 4006 "\trecords [--tree] [--raw] [--xml] bdaddr\n"; 4007 4008 /* 4009 * Request possible SDP service records 4010 */ 4011 static int cmd_records(int argc, char **argv) 4012 { 4013 struct search_context context; 4014 uint32_t base[] = { 0x10000, 0x10300, 0x10500, 4015 0x1002e, 0x110b, 0x90000, 0x2008000, 4016 0x4000000, 0x100000, 0x1000000, 4017 0x4f491100, 0x4f491200 }; 4018 bdaddr_t bdaddr; 4019 unsigned int i, n, num = 32; 4020 int opt, err = 0; 4021 4022 /* Initialise context */ 4023 memset(&context, '\0', sizeof(struct search_context)); 4024 4025 for_each_opt(opt, records_options, 0) { 4026 switch (opt) { 4027 case 't': 4028 context.view = TREE_VIEW; 4029 break; 4030 case 'r': 4031 context.view = RAW_VIEW; 4032 break; 4033 case 'x': 4034 context.view = XML_VIEW; 4035 break; 4036 default: 4037 printf("%s", records_help); 4038 return -1; 4039 } 4040 } 4041 4042 argc -= optind; 4043 argv += optind; 4044 4045 if (argc < 1) { 4046 printf("%s", records_help); 4047 return -1; 4048 } 4049 4050 /* Convert command line parameters */ 4051 estr2ba(argv[0], &bdaddr); 4052 4053 for (i = 0; i < sizeof(base) / sizeof(uint32_t); i++) 4054 for (n = 0; n < num; n++) { 4055 context.handle = base[i] + n; 4056 err = get_service(&bdaddr, &context, 1); 4057 if (err < 0) 4058 goto done; 4059 } 4060 4061 done: 4062 return 0; 4063 } 4064 4065 static struct option get_options[] = { 4066 { "help", 0, 0, 'h' }, 4067 { "bdaddr", 1, 0, 'b' }, 4068 { "tree", 0, 0, 't' }, 4069 { "raw", 0, 0, 'r' }, 4070 { "xml", 0, 0, 'x' }, 4071 { 0, 0, 0, 0 } 4072 }; 4073 4074 static const char *get_help = 4075 "Usage:\n" 4076 "\tget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\n"; 4077 4078 /* 4079 * Get a specific SDP record on the local SDP server 4080 */ 4081 static int cmd_get(int argc, char **argv) 4082 { 4083 struct search_context context; 4084 bdaddr_t bdaddr; 4085 int has_addr = 0; 4086 int opt; 4087 4088 /* Initialise context */ 4089 memset(&context, '\0', sizeof(struct search_context)); 4090 4091 for_each_opt(opt, get_options, 0) { 4092 switch (opt) { 4093 case 'b': 4094 estr2ba(optarg, &bdaddr); 4095 has_addr = 1; 4096 break; 4097 case 't': 4098 context.view = TREE_VIEW; 4099 break; 4100 case 'r': 4101 context.view = RAW_VIEW; 4102 break; 4103 case 'x': 4104 context.view = XML_VIEW; 4105 break; 4106 default: 4107 printf("%s", get_help); 4108 return -1; 4109 } 4110 } 4111 4112 argc -= optind; 4113 argv += optind; 4114 4115 if (argc < 1) { 4116 printf("%s", get_help); 4117 return -1; 4118 } 4119 4120 /* Convert command line parameters */ 4121 context.handle = strtoul(argv[0], 0, 16); 4122 4123 return get_service(has_addr ? &bdaddr : BDADDR_LOCAL, &context, 0); 4124 } 4125 4126 static struct { 4127 char *cmd; 4128 int (*func)(int argc, char **argv); 4129 char *doc; 4130 } command[] = { 4131 { "search", cmd_search, "Search for a service" }, 4132 { "browse", cmd_browse, "Browse all available services" }, 4133 { "records", cmd_records, "Request all records" }, 4134 { "add", cmd_add, "Add local service" }, 4135 { "del", cmd_del, "Delete local service" }, 4136 { "get", cmd_get, "Get local service" }, 4137 { "setattr", cmd_setattr, "Set/Add attribute to a SDP record" }, 4138 { "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" }, 4139 { 0, 0, 0 } 4140 }; 4141 4142 static void usage(void) 4143 { 4144 int i, pos = 0; 4145 4146 printf("sdptool - SDP tool v%s\n", VERSION); 4147 printf("Usage:\n" 4148 "\tsdptool [options] <command> [command parameters]\n"); 4149 printf("Options:\n" 4150 "\t-h\t\tDisplay help\n" 4151 "\t-i\t\tSpecify source interface\n"); 4152 4153 printf("Commands:\n"); 4154 for (i = 0; command[i].cmd; i++) 4155 printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc); 4156 4157 printf("\nServices:\n\t"); 4158 for (i = 0; service[i].name; i++) { 4159 printf("%s ", service[i].name); 4160 pos += strlen(service[i].name) + 1; 4161 if (pos > 60) { 4162 printf("\n\t"); 4163 pos = 0; 4164 } 4165 } 4166 printf("\n"); 4167 } 4168 4169 static struct option main_options[] = { 4170 { "help", 0, 0, 'h' }, 4171 { "device", 1, 0, 'i' }, 4172 { 0, 0, 0, 0 } 4173 }; 4174 4175 int main(int argc, char *argv[]) 4176 { 4177 int i, opt; 4178 4179 bacpy(&interface, BDADDR_ANY); 4180 4181 while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { 4182 switch(opt) { 4183 case 'i': 4184 if (!strncmp(optarg, "hci", 3)) 4185 hci_devba(atoi(optarg + 3), &interface); 4186 else 4187 str2ba(optarg, &interface); 4188 break; 4189 4190 case 'h': 4191 usage(); 4192 exit(0); 4193 4194 default: 4195 exit(1); 4196 } 4197 } 4198 4199 argc -= optind; 4200 argv += optind; 4201 optind = 0; 4202 4203 if (argc < 1) { 4204 usage(); 4205 exit(1); 4206 } 4207 4208 for (i = 0; command[i].cmd; i++) 4209 if (strncmp(command[i].cmd, argv[0], 4) == 0) 4210 return command[i].func(argc, argv); 4211 4212 return 1; 4213 } 4214