3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2001-2002 Nokia Corporation
6
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
8
* Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
9
* Copyright (C) 2002-2003 Jean Tourrilhes <jt@hpl.hp.com>
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.
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.
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
38
#include <sys/socket.h>
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>
46
#include <netinet/in.h>
50
#ifndef APPLE_AGENT_SVCLASS_ID
51
#define APPLE_AGENT_SVCLASS_ID 0x2112
54
#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1)
57
* Convert a string to a BDADDR, with a few "enhancements" - Jean II
59
static int estr2ba(char *str, bdaddr_t *ba)
61
/* Only trap "local", "any" is already dealt with */
62
if(!strcmp(str, "local")) {
63
bacpy(ba, BDADDR_LOCAL);
66
return str2ba(str, ba);
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 */
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 */
82
typedef int (*handler_t)(bdaddr_t *bdaddr, struct search_context *arg);
84
static char UUID_str[MAX_LEN_UUID_STR];
85
static bdaddr_t interface;
87
/* Definition of attribute members */
92
/* Definition of an attribute */
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 */
100
/* Definition of a service or protocol */
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 */
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 */
115
/* Context information about the whole service */
116
struct service_context {
117
struct uuid_def *service; /* Service UUID, if known */
120
/* Allow us to do nice formatting of the lists */
121
static char *indent_spaces = " ";
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
128
/* Definition of the optional arguments in protocol list */
129
static struct member_def protocol_members[] = {
135
/* Definition of the optional arguments in profile list */
136
static struct member_def profile_members[] = {
141
/* Definition of the optional arguments in Language list */
142
static struct member_def language_members[] = {
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) */
170
const int attrib_max = sizeof(attrib_names)/sizeof(struct attrib_def);
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 },
178
/* Name of the various SPD attributes. See BT assigned numbers */
179
static struct attrib_def browse_attrib_names[] = {
180
{ 0x200, "GroupID", NULL, 0 },
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 },
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 },
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 },
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 },
229
/* Name of the various GOEP attributes. See BT assigned numbers */
230
static struct attrib_def goep_attrib_names[] = {
231
{ 0x200, "GoepL2capPsm", NULL, 0 },
234
/* Same for the UUIDs. See BT assigned numbers */
235
static struct uuid_def uuid16_names[] = {
236
/* -- Protocols -- */
237
{ 0x0001, "SDP", NULL, 0 },
238
{ 0x0002, "UDP", NULL, 0 },
239
{ 0x0003, "RFCOMM", NULL, 0 },
240
{ 0x0004, "TCP", NULL, 0 },
241
{ 0x0005, "TCS-BIN", NULL, 0 },
242
{ 0x0006, "TCS-AT", NULL, 0 },
243
{ 0x0008, "OBEX", NULL, 0 },
244
{ 0x0009, "IP", NULL, 0 },
245
{ 0x000a, "FTP", NULL, 0 },
246
{ 0x000c, "HTTP", NULL, 0 },
247
{ 0x000e, "WSP", NULL, 0 },
248
{ 0x000f, "BNEP", NULL, 0 },
249
{ 0x0010, "UPnP/ESDP", NULL, 0 },
250
{ 0x0011, "HIDP", NULL, 0 },
251
{ 0x0012, "HardcopyControlChannel", NULL, 0 },
252
{ 0x0014, "HardcopyDataChannel", NULL, 0 },
253
{ 0x0016, "HardcopyNotification", NULL, 0 },
254
{ 0x0017, "AVCTP", NULL, 0 },
255
{ 0x0019, "AVDTP", NULL, 0 },
256
{ 0x001b, "CMTP", NULL, 0 },
257
{ 0x001d, "UDI_C-Plane", NULL, 0 },
258
{ 0x0100, "L2CAP", NULL, 0 },
260
{ 0x1000, "ServiceDiscoveryServerServiceClassID",
261
sdp_attrib_names, sizeof(sdp_attrib_names)/sizeof(struct attrib_def) },
262
{ 0x1001, "BrowseGroupDescriptorServiceClassID",
263
browse_attrib_names, sizeof(browse_attrib_names)/sizeof(struct attrib_def) },
264
{ 0x1002, "PublicBrowseGroup", NULL, 0 },
265
{ 0x1101, "SerialPort", NULL, 0 },
266
{ 0x1102, "LANAccessUsingPPP", NULL, 0 },
267
{ 0x1103, "DialupNetworking (DUN)", NULL, 0 },
268
{ 0x1104, "IrMCSync", NULL, 0 },
269
{ 0x1105, "OBEXObjectPush",
270
goep_attrib_names, sizeof(goep_attrib_names)/sizeof(struct attrib_def) },
271
{ 0x1106, "OBEXFileTransfer",
272
goep_attrib_names, sizeof(goep_attrib_names)/sizeof(struct attrib_def) },
273
{ 0x1107, "IrMCSyncCommand", NULL, 0 },
275
audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) },
276
{ 0x1109, "CordlessTelephony", NULL, 0 },
277
{ 0x110a, "AudioSource", NULL, 0 },
278
{ 0x110b, "AudioSink", NULL, 0 },
279
{ 0x110c, "RemoteControlTarget", NULL, 0 },
280
{ 0x110d, "AdvancedAudio", NULL, 0 },
281
{ 0x110e, "RemoteControl", NULL, 0 },
282
{ 0x110f, "VideoConferencing", NULL, 0 },
283
{ 0x1110, "Intercom", NULL, 0 },
284
{ 0x1111, "Fax", NULL, 0 },
285
{ 0x1112, "HeadsetAudioGateway", NULL, 0 },
286
{ 0x1113, "WAP", NULL, 0 },
287
{ 0x1114, "WAP Client", NULL, 0 },
288
{ 0x1115, "PANU (PAN/BNEP)",
289
pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },
290
{ 0x1116, "NAP (PAN/BNEP)",
291
pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },
292
{ 0x1117, "GN (PAN/BNEP)",
293
pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },
294
{ 0x1118, "DirectPrinting (BPP)", NULL, 0 },
295
{ 0x1119, "ReferencePrinting (BPP)", NULL, 0 },
296
{ 0x111a, "Imaging (BIP)", NULL, 0 },
297
{ 0x111b, "ImagingResponder (BIP)", NULL, 0 },
298
{ 0x111c, "ImagingAutomaticArchive (BIP)", NULL, 0 },
299
{ 0x111d, "ImagingReferencedObjects (BIP)", NULL, 0 },
300
{ 0x111e, "Handsfree", NULL, 0 },
301
{ 0x111f, "HandsfreeAudioGateway", NULL, 0 },
302
{ 0x1120, "DirectPrintingReferenceObjectsService (BPP)", NULL, 0 },
303
{ 0x1121, "ReflectedUI (BPP)", NULL, 0 },
304
{ 0x1122, "BasicPrinting (BPP)", NULL, 0 },
305
{ 0x1123, "PrintingStatus (BPP)", NULL, 0 },
306
{ 0x1124, "HumanInterfaceDeviceService (HID)",
307
hid_attrib_names, sizeof(hid_attrib_names)/sizeof(struct attrib_def) },
308
{ 0x1125, "HardcopyCableReplacement (HCR)", NULL, 0 },
309
{ 0x1126, "HCR_Print (HCR)", NULL, 0 },
310
{ 0x1127, "HCR_Scan (HCR)", NULL, 0 },
311
{ 0x1128, "Common ISDN Access (CIP)", NULL, 0 },
312
{ 0x1129, "VideoConferencingGW (VCP)", NULL, 0 },
313
{ 0x112a, "UDI-MT", NULL, 0 },
314
{ 0x112b, "UDI-TA", NULL, 0 },
315
{ 0x112c, "Audio/Video", NULL, 0 },
316
{ 0x112d, "SIM Access (SAP)", NULL, 0 },
317
{ 0x112e, "Phonebook Access (PBAP) - PCE", NULL, 0 },
318
{ 0x112f, "Phonebook Access (PBAP) - PSE", NULL, 0 },
319
{ 0x1130, "Phonebook Access (PBAP)", NULL, 0 },
321
{ 0x1200, "PnPInformation",
322
did_attrib_names, sizeof(did_attrib_names)/sizeof(struct attrib_def) },
323
{ 0x1201, "GenericNetworking", NULL, 0 },
324
{ 0x1202, "GenericFileTransfer", NULL, 0 },
325
{ 0x1203, "GenericAudio",
326
audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) },
327
{ 0x1204, "GenericTelephony", NULL, 0 },
329
{ 0x1303, "VideoSource", NULL, 0 },
330
{ 0x1304, "VideoSink", NULL, 0 },
331
{ 0x1305, "VideoDistribution", NULL, 0 },
332
{ 0x1400, "HDP", NULL, 0 },
333
{ 0x1401, "HDPSource", NULL, 0 },
334
{ 0x1402, "HDPSink", NULL, 0 },
335
{ 0x2112, "AppleAgent", NULL, 0 },
338
static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def);
340
static void sdp_data_printf(sdp_data_t *, struct attrib_context *, int);
344
* The BT assigned numbers only list UUID16, so I'm not sure the
345
* other types will ever get used...
347
static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent)
350
if (uuid->type == SDP_UUID16) {
351
uint16_t uuidNum = uuid->value.uuid16;
352
struct uuid_def *uuidDef = NULL;
355
for (i = 0; i < uuid16_max; i++)
356
if (uuid16_names[i].num == uuidNum) {
357
uuidDef = &uuid16_names[i];
361
/* Check if it's the service attribute */
362
if (context->attrib && context->attrib->num == SERVICE_ATTR) {
363
/* We got the service ID !!! */
364
context->service = uuidDef;
368
printf("%.*sUUID16 : 0x%.4x - %s\n",
369
indent, indent_spaces, uuidNum, uuidDef->name);
371
printf("%.*sUUID16 : 0x%.4x\n",
372
indent, indent_spaces, uuidNum);
373
} else if (uuid->type == SDP_UUID32) {
374
struct uuid_def *uuidDef = NULL;
377
if (!(uuid->value.uuid32 & 0xffff0000)) {
378
uint16_t uuidNum = uuid->value.uuid32;
379
for (i = 0; i < uuid16_max; i++)
380
if (uuid16_names[i].num == uuidNum) {
381
uuidDef = &uuid16_names[i];
387
printf("%.*sUUID32 : 0x%.8x - %s\n",
388
indent, indent_spaces, uuid->value.uuid32, uuidDef->name);
390
printf("%.*sUUID32 : 0x%.8x\n",
391
indent, indent_spaces, uuid->value.uuid32);
392
} else if (uuid->type == SDP_UUID128) {
394
unsigned short data1;
395
unsigned short data2;
396
unsigned short data3;
398
unsigned short data5;
400
memcpy(&data0, &uuid->value.uuid128.data[0], 4);
401
memcpy(&data1, &uuid->value.uuid128.data[4], 2);
402
memcpy(&data2, &uuid->value.uuid128.data[6], 2);
403
memcpy(&data3, &uuid->value.uuid128.data[8], 2);
404
memcpy(&data4, &uuid->value.uuid128.data[10], 4);
405
memcpy(&data5, &uuid->value.uuid128.data[14], 2);
407
printf("%.*sUUID128 : 0x%.8x-%.4x-%.4x-%.4x-%.8x-%.4x\n",
408
indent, indent_spaces,
409
ntohl(data0), ntohs(data1), ntohs(data2),
410
ntohs(data3), ntohl(data4), ntohs(data5));
412
printf("%.*sEnum type of UUID not set\n",
413
indent, indent_spaces);
415
printf("%.*sNull passed to print UUID\n",
416
indent, indent_spaces);
420
* Parse a sequence of data elements (i.e. a list)
422
static void printf_dataseq(sdp_data_t * pData, struct attrib_context *context, int indent)
424
sdp_data_t *sdpdata = NULL;
428
context->member_index = 0;
430
sdp_data_printf(sdpdata, context, indent + 2);
431
sdpdata = sdpdata->next;
432
context->member_index++;
435
printf("%.*sBroken dataseq link\n", indent, indent_spaces);
440
* Parse a single data element (either in the attribute or in a data
443
static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent)
445
char *member_name = NULL;
447
/* Find member name. Almost black magic ;-) */
448
if (context && context->attrib && context->attrib->members &&
449
context->member_index < context->attrib->member_max) {
450
member_name = context->attrib->members[context->member_index].name;
453
switch (sdpdata->dtd) {
455
printf("%.*sNil\n", indent, indent_spaces);
469
printf("%.*s%s (Integer) : 0x%x\n",
470
indent, indent_spaces, member_name, sdpdata->val.uint32);
472
printf("%.*sInteger : 0x%x\n", indent, indent_spaces,
473
sdpdata->val.uint32);
480
//printf("%.*sUUID\n", indent, indent_spaces);
481
sdp_uuid_printf(&sdpdata->val.uuid, context, indent);
487
if (sdpdata->unitSize > (int) strlen(sdpdata->val.str)) {
489
printf("%.*sData :", indent, indent_spaces);
490
for (i = 0; i < sdpdata->unitSize; i++)
491
printf(" %02x", (unsigned char) sdpdata->val.str[i]);
494
printf("%.*sText : \"%s\"\n", indent, indent_spaces, sdpdata->val.str);
499
printf("%.*sURL : %s\n", indent, indent_spaces, sdpdata->val.str);
505
printf("%.*sData Sequence\n", indent, indent_spaces);
506
printf_dataseq(sdpdata->val.dataseq, context, indent);
512
printf("%.*sData Sequence Alternates\n", indent, indent_spaces);
513
printf_dataseq(sdpdata->val.dataseq, context, indent);
519
* Parse a single attribute.
521
static void print_tree_attr_func(void *value, void *userData)
523
sdp_data_t *sdpdata = value;
525
struct service_context *service = (struct service_context *) userData;
526
struct attrib_context context;
527
struct attrib_def *attrDef = NULL;
533
attrId = sdpdata->attrId;
534
/* Search amongst the generic attributes */
535
for (i = 0; i < attrib_max; i++)
536
if (attrib_names[i].num == attrId) {
537
attrDef = &attrib_names[i];
540
/* Search amongst the specific attributes of this service */
541
if ((attrDef == NULL) && (service->service != NULL) &&
542
(service->service->attribs != NULL)) {
543
struct attrib_def *svc_attribs = service->service->attribs;
544
int svc_attrib_max = service->service->attrib_max;
545
for (i = 0; i < svc_attrib_max; i++)
546
if (svc_attribs[i].num == attrId) {
547
attrDef = &svc_attribs[i];
553
printf("Attribute Identifier : 0x%x - %s\n", attrId, attrDef->name);
555
printf("Attribute Identifier : 0x%x\n", attrId);
557
context.service = service->service;
558
context.attrib = attrDef;
559
context.member_index = 0;
560
/* Parse attribute members */
561
sdp_data_printf(sdpdata, &context, 2);
563
service->service = context.service;
567
* Main entry point of this library. Parse a SDP record.
568
* We assume the record has already been read, parsed and cached
571
static void print_tree_attr(sdp_record_t *rec)
573
if (rec && rec->attrlist) {
574
struct service_context service = { NULL };
575
sdp_list_foreach(rec->attrlist, print_tree_attr_func, &service);
579
static void print_raw_data(sdp_data_t *data, int indent)
581
struct uuid_def *def;
587
for (i = 0; i < indent; i++)
595
printf("Bool %s\n", data->val.uint8 ? "True" : "False");
598
printf("UINT8 0x%02x\n", data->val.uint8);
601
printf("UINT16 0x%04x\n", data->val.uint16);
604
printf("UINT32 0x%08x\n", data->val.uint32);
607
printf("UINT64 0x%016jx\n", data->val.uint64);
610
printf("UINT128 ...\n");
613
printf("INT8 %d\n", data->val.int8);
616
printf("INT16 %d\n", data->val.int16);
619
printf("INT32 %d\n", data->val.int32);
622
printf("INT64 %jd\n", data->val.int64);
625
printf("INT128 ...\n");
630
switch (data->val.uuid.type) {
633
for (i = 0; i < uuid16_max; i++)
634
if (uuid16_names[i].num == data->val.uuid.value.uuid16) {
635
def = &uuid16_names[i];
639
printf("UUID16 0x%04x - %s\n", data->val.uuid.value.uuid16, def->name);
641
printf("UUID16 0x%04x\n", data->val.uuid.value.uuid16);
645
if (!(data->val.uuid.value.uuid32 & 0xffff0000)) {
646
uint16_t value = data->val.uuid.value.uuid32;
647
for (i = 0; i < uuid16_max; i++)
648
if (uuid16_names[i].num == value) {
649
def = &uuid16_names[i];
654
printf("UUID32 0x%08x - %s\n", data->val.uuid.value.uuid32, def->name);
656
printf("UUID32 0x%08x\n", data->val.uuid.value.uuid32);
660
for (i = 0; i < 16; i++) {
669
printf("%02x", (unsigned char ) data->val.uuid.value.uuid128.data[i]);
674
printf("UUID type 0x%02x\n", data->val.uuid.type);
682
for (i = 0; i < data->unitSize; i++) {
683
if (i == (data->unitSize - 1) && data->val.str[i] == '\0')
685
if (!isprint(data->val.str[i])) {
692
for (i = 0; i < data->unitSize; i++)
693
printf(" %02x", (unsigned char) data->val.str[i]);
696
for (i = 0; i < data->unitSize; i++)
697
printf("%c", data->val.str[i]);
704
printf("URL %s\n", data->val.str);
709
printf("Sequence\n");
710
print_raw_data(data->val.dataseq, indent + 1);
715
printf("Alternate\n");
716
print_raw_data(data->val.dataseq, indent + 1);
719
printf("Unknown type 0x%02x\n", data->dtd);
723
print_raw_data(data->next, indent);
726
static void print_raw_attr_func(void *value, void *userData)
728
sdp_data_t *data = (sdp_data_t *) value;
729
struct attrib_def *def = NULL;
735
/* Search amongst the generic attributes */
736
for (i = 0; i < attrib_max; i++)
737
if (attrib_names[i].num == data->attrId) {
738
def = &attrib_names[i];
743
printf("\tAttribute 0x%04x - %s\n", data->attrId, def->name);
745
printf("\tAttribute 0x%04x\n", data->attrId);
747
print_raw_data(data, 2);
750
static void print_raw_attr(sdp_record_t *rec)
752
if (rec && rec->attrlist) {
753
printf("Sequence\n");
754
sdp_list_foreach(rec->attrlist, print_raw_attr_func, 0);
759
* Set attributes with single values in SDP record
762
static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *value)
764
sdp_list_t *attrid_list;
765
uint32_t range = 0x0000ffff;
769
/* Get the old SDP record */
770
attrid_list = sdp_list_append(NULL, &range);
771
rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attrid_list);
772
sdp_list_free(attrid_list, NULL);
775
printf("Service get request failed.\n");
779
/* Check the type of attribute */
780
if (!strncasecmp(value, "u0x", 3)) {
782
uint16_t value_int = 0;
784
value_int = strtoul(value + 3, NULL, 16);
785
sdp_uuid16_create(&value_uuid, value_int);
786
printf("Adding attrib 0x%X uuid16 0x%X to record 0x%X\n",
787
attrib, value_int, handle);
789
sdp_attr_add_new(rec, attrib, SDP_UUID16, &value_uuid.value.uuid16);
790
} else if (!strncasecmp(value, "0x", 2)) {
793
value_int = strtoul(value + 2, NULL, 16);
794
printf("Adding attrib 0x%X int 0x%X to record 0x%X\n",
795
attrib, value_int, handle);
797
sdp_attr_add_new(rec, attrib, SDP_UINT32, &value_int);
800
printf("Adding attrib 0x%X string \"%s\" to record 0x%X\n",
801
attrib, value, handle);
803
/* Add/Update our attribute to the record */
804
sdp_attr_add_new(rec, attrib, SDP_TEXT_STR8, value);
807
/* Update on the server */
808
ret = sdp_device_record_update(sess, &interface, rec);
810
printf("Service Record update failed (%d).\n", errno);
811
sdp_record_free(rec);
815
static struct option set_options[] = {
816
{ "help", 0, 0, 'h' },
820
static const char *set_help =
822
"\tget record_handle attrib_id attrib_value\n";
825
* Add an attribute to an existing SDP record on the local SDP server
827
static int cmd_setattr(int argc, char **argv)
834
for_each_opt(opt, set_options, NULL) {
837
printf("%s", set_help);
846
printf("%s", set_help);
850
/* Convert command line args */
851
handle = strtoul(argv[0], NULL, 16);
852
attrib = strtoul(argv[1], NULL, 16);
855
sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
859
status = set_attrib(sess, handle, attrib, argv[2]);
866
* We do only simple data sequences. Sequence of sequences is a pain ;-)
869
static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int argc, char **argv)
871
sdp_list_t *attrid_list;
872
uint32_t range = 0x0000ffff;
874
sdp_data_t *pSequenceHolder = NULL;
878
uint8_t uuid16 = SDP_UUID16;
879
uint8_t uint32 = SDP_UINT32;
880
uint8_t str8 = SDP_TEXT_STR8;
883
/* Get the old SDP record */
884
attrid_list = sdp_list_append(NULL, &range);
885
rec = sdp_service_attr_req(session, handle, SDP_ATTR_REQ_RANGE, attrid_list);
886
sdp_list_free(attrid_list, NULL);
889
printf("Service get request failed.\n");
894
dtdArray = (void **)malloc(argc * sizeof(void *));
895
valueArray = (void **)malloc(argc * sizeof(void *));
896
allocArray = (void **)malloc(argc * sizeof(void *));
898
/* Loop on all args, add them in arrays */
899
for (i = 0; i < argc; i++) {
900
/* Check the type of attribute */
901
if (!strncasecmp(argv[i], "u0x", 3)) {
903
uint16_t value_int = strtoul((argv[i]) + 3, NULL, 16);
904
uuid_t *value_uuid = (uuid_t *) malloc(sizeof(uuid_t));
905
allocArray[i] = value_uuid;
906
sdp_uuid16_create(value_uuid, value_int);
908
printf("Adding uuid16 0x%X to record 0x%X\n", value_int, handle);
909
dtdArray[i] = &uuid16;
910
valueArray[i] = &value_uuid->value.uuid16;
911
} else if (!strncasecmp(argv[i], "0x", 2)) {
913
uint32_t *value_int = (uint32_t *) malloc(sizeof(int));
914
allocArray[i] = value_int;
915
*value_int = strtoul((argv[i]) + 2, NULL, 16);
917
printf("Adding int 0x%X to record 0x%X\n", *value_int, handle);
918
dtdArray[i] = &uint32;
919
valueArray[i] = value_int;
922
printf("Adding string \"%s\" to record 0x%X\n", argv[i], handle);
924
valueArray[i] = argv[i];
928
/* Add this sequence to the attrib list */
929
pSequenceHolder = sdp_seq_alloc(dtdArray, valueArray, argc);
930
if (pSequenceHolder) {
931
sdp_attr_replace(rec, attrib, pSequenceHolder);
933
/* Update on the server */
934
ret = sdp_device_record_update(session, &interface, rec);
936
printf("Service Record update failed (%d).\n", errno);
938
printf("Failed to create pSequenceHolder\n");
941
for (i = 0; i < argc; i++)
948
sdp_record_free(rec);
953
static struct option seq_options[] = {
954
{ "help", 0, 0, 'h' },
958
static const char *seq_help =
960
"\tget record_handle attrib_id attrib_values\n";
963
* Add an attribute sequence to an existing SDP record
964
* on the local SDP server
966
static int cmd_setseq(int argc, char **argv)
973
for_each_opt(opt, seq_options, NULL) {
976
printf("%s", seq_help);
985
printf("%s", seq_help);
989
/* Convert command line args */
990
handle = strtoul(argv[0], NULL, 16);
991
attrib = strtoul(argv[1], NULL, 16);
997
sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
1001
status = set_attribseq(sess, handle, attrib, argc, argv);
1007
static void print_service_class(void *value, void *userData)
1009
char ServiceClassUUID_str[MAX_LEN_SERVICECLASS_UUID_STR];
1010
uuid_t *uuid = (uuid_t *)value;
1012
sdp_uuid2strn(uuid, UUID_str, MAX_LEN_UUID_STR);
1013
sdp_svclass_uuid2strn(uuid, ServiceClassUUID_str, MAX_LEN_SERVICECLASS_UUID_STR);
1014
if (uuid->type != SDP_UUID128)
1015
printf(" \"%s\" (0x%s)\n", ServiceClassUUID_str, UUID_str);
1017
printf(" UUID 128: %s\n", UUID_str);
1020
static void print_service_desc(void *value, void *user)
1022
char str[MAX_LEN_PROTOCOL_UUID_STR];
1023
sdp_data_t *p = (sdp_data_t *)value, *s;
1024
int i = 0, proto = 0;
1026
for (; p; p = p->next, i++) {
1031
sdp_uuid2strn(&p->val.uuid, UUID_str, MAX_LEN_UUID_STR);
1032
sdp_proto_uuid2strn(&p->val.uuid, str, sizeof(str));
1033
proto = sdp_uuid_to_proto(&p->val.uuid);
1034
printf(" \"%s\" (0x%s)\n", str, UUID_str);
1037
if (proto == RFCOMM_UUID)
1038
printf(" Channel: %d\n", p->val.uint8);
1040
printf(" uint8: 0x%x\n", p->val.uint8);
1043
if (proto == L2CAP_UUID) {
1045
printf(" PSM: %d\n", p->val.uint16);
1047
printf(" Version: 0x%04x\n", p->val.uint16);
1048
} else if (proto == BNEP_UUID)
1050
printf(" Version: 0x%04x\n", p->val.uint16);
1052
printf(" uint16: 0x%x\n", p->val.uint16);
1054
printf(" uint16: 0x%x\n", p->val.uint16);
1058
for (s = p->val.dataseq; s; s = s->next)
1059
printf(" %x", s->val.uint16);
1064
for (s = p->val.dataseq; s; s = s->next)
1065
printf(" %x", s->val.uint8);
1069
printf(" FIXME: dtd=0%x\n", p->dtd);
1075
static void print_lang_attr(void *value, void *user)
1077
sdp_lang_attr_t *lang = (sdp_lang_attr_t *)value;
1078
printf(" code_ISO639: 0x%02x\n", lang->code_ISO639);
1079
printf(" encoding: 0x%02x\n", lang->encoding);
1080
printf(" base_offset: 0x%02x\n", lang->base_offset);
1083
static void print_access_protos(void *value, void *userData)
1085
sdp_list_t *protDescSeq = (sdp_list_t *)value;
1086
sdp_list_foreach(protDescSeq, print_service_desc, 0);
1089
static void print_profile_desc(void *value, void *userData)
1091
sdp_profile_desc_t *desc = (sdp_profile_desc_t *)value;
1092
char str[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR];
1094
sdp_uuid2strn(&desc->uuid, UUID_str, MAX_LEN_UUID_STR);
1095
sdp_profile_uuid2strn(&desc->uuid, str, MAX_LEN_PROFILEDESCRIPTOR_UUID_STR);
1097
printf(" \"%s\" (0x%s)\n", str, UUID_str);
1099
printf(" Version: 0x%04x\n", desc->version);
1103
* Parse a SDP record in user friendly form.
1105
static void print_service_attr(sdp_record_t *rec)
1107
sdp_list_t *list = 0, *proto = 0;
1109
sdp_record_print(rec);
1111
printf("Service RecHandle: 0x%x\n", rec->handle);
1113
if (sdp_get_service_classes(rec, &list) == 0) {
1114
printf("Service Class ID List:\n");
1115
sdp_list_foreach(list, print_service_class, 0);
1116
sdp_list_free(list, free);
1118
if (sdp_get_access_protos(rec, &proto) == 0) {
1119
printf("Protocol Descriptor List:\n");
1120
sdp_list_foreach(proto, print_access_protos, 0);
1121
sdp_list_foreach(proto, (sdp_list_func_t)sdp_list_free, 0);
1122
sdp_list_free(proto, 0);
1124
if (sdp_get_lang_attr(rec, &list) == 0) {
1125
printf("Language Base Attr List:\n");
1126
sdp_list_foreach(list, print_lang_attr, 0);
1127
sdp_list_free(list, free);
1129
if (sdp_get_profile_descs(rec, &list) == 0) {
1130
printf("Profile Descriptor List:\n");
1131
sdp_list_foreach(list, print_profile_desc, 0);
1132
sdp_list_free(list, free);
1137
* Support for Service (de)registration
1145
unsigned int profile;
1151
static int add_sp(sdp_session_t *session, svc_info_t *si)
1153
sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
1154
uuid_t root_uuid, sp_uuid, l2cap, rfcomm;
1155
sdp_profile_desc_t profile;
1156
sdp_record_t record;
1157
uint8_t u8 = si->channel ? si->channel : 1;
1158
sdp_data_t *channel;
1161
memset(&record, 0, sizeof(sdp_record_t));
1162
record.handle = si->handle;
1163
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1164
root = sdp_list_append(0, &root_uuid);
1165
sdp_set_browse_groups(&record, root);
1166
sdp_list_free(root, 0);
1168
sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID);
1169
svclass_id = sdp_list_append(0, &sp_uuid);
1170
sdp_set_service_classes(&record, svclass_id);
1171
sdp_list_free(svclass_id, 0);
1173
sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
1174
profile.version = 0x0100;
1175
profiles = sdp_list_append(0, &profile);
1176
sdp_set_profile_descs(&record, profiles);
1177
sdp_list_free(profiles, 0);
1179
sdp_uuid16_create(&l2cap, L2CAP_UUID);
1180
proto[0] = sdp_list_append(0, &l2cap);
1181
apseq = sdp_list_append(0, proto[0]);
1183
sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
1184
proto[1] = sdp_list_append(0, &rfcomm);
1185
channel = sdp_data_alloc(SDP_UINT8, &u8);
1186
proto[1] = sdp_list_append(proto[1], channel);
1187
apseq = sdp_list_append(apseq, proto[1]);
1189
aproto = sdp_list_append(0, apseq);
1190
sdp_set_access_protos(&record, aproto);
1192
sdp_add_lang_attr(&record);
1194
sdp_set_info_attr(&record, "Serial Port", "BlueZ", "COM Port");
1196
sdp_set_url_attr(&record, "http://www.bluez.org/",
1197
"http://www.bluez.org/", "http://www.bluez.org/");
1199
sdp_set_service_id(&record, sp_uuid);
1200
sdp_set_service_ttl(&record, 0xffff);
1201
sdp_set_service_avail(&record, 0xff);
1202
sdp_set_record_state(&record, 0x00001234);
1204
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1205
printf("Service Record registration failed\n");
1210
printf("Serial Port service registered\n");
1213
sdp_data_free(channel);
1214
sdp_list_free(proto[0], 0);
1215
sdp_list_free(proto[1], 0);
1216
sdp_list_free(apseq, 0);
1217
sdp_list_free(aproto, 0);
1222
static int add_dun(sdp_session_t *session, svc_info_t *si)
1224
sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto;
1225
uuid_t rootu, dun, gn, l2cap, rfcomm;
1226
sdp_profile_desc_t profile;
1227
sdp_list_t *proto[2];
1228
sdp_record_t record;
1229
uint8_t u8 = si->channel ? si->channel : 2;
1230
sdp_data_t *channel;
1233
memset(&record, 0, sizeof(sdp_record_t));
1234
record.handle = si->handle;
1236
sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP);
1237
root = sdp_list_append(0, &rootu);
1238
sdp_set_browse_groups(&record, root);
1240
sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
1241
svclass_id = sdp_list_append(0, &dun);
1242
sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID);
1243
svclass_id = sdp_list_append(svclass_id, &gn);
1244
sdp_set_service_classes(&record, svclass_id);
1246
sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
1247
profile.version = 0x0100;
1248
pfseq = sdp_list_append(0, &profile);
1249
sdp_set_profile_descs(&record, pfseq);
1251
sdp_uuid16_create(&l2cap, L2CAP_UUID);
1252
proto[0] = sdp_list_append(0, &l2cap);
1253
apseq = sdp_list_append(0, proto[0]);
1255
sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
1256
proto[1] = sdp_list_append(0, &rfcomm);
1257
channel = sdp_data_alloc(SDP_UINT8, &u8);
1258
proto[1] = sdp_list_append(proto[1], channel);
1259
apseq = sdp_list_append(apseq, proto[1]);
1261
aproto = sdp_list_append(0, apseq);
1262
sdp_set_access_protos(&record, aproto);
1264
sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0);
1266
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1267
printf("Service Record registration failed\n");
1272
printf("Dial-Up Networking service registered\n");
1275
sdp_data_free(channel);
1276
sdp_list_free(proto[0], 0);
1277
sdp_list_free(proto[1], 0);
1278
sdp_list_free(apseq, 0);
1279
sdp_list_free(aproto, 0);
1284
static int add_fax(sdp_session_t *session, svc_info_t *si)
1286
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1287
uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid;
1288
sdp_profile_desc_t profile;
1289
sdp_list_t *aproto, *proto[2];
1290
sdp_record_t record;
1291
uint8_t u8 = si->channel? si->channel : 3;
1292
sdp_data_t *channel;
1295
memset(&record, 0, sizeof(sdp_record_t));
1296
record.handle = si->handle;
1298
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1299
root = sdp_list_append(0, &root_uuid);
1300
sdp_set_browse_groups(&record, root);
1302
sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID);
1303
svclass_id = sdp_list_append(0, &fax_uuid);
1304
sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
1305
svclass_id = sdp_list_append(svclass_id, &tel_uuid);
1306
sdp_set_service_classes(&record, svclass_id);
1308
sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID);
1309
profile.version = 0x0100;
1310
pfseq = sdp_list_append(0, &profile);
1311
sdp_set_profile_descs(&record, pfseq);
1313
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1314
proto[0] = sdp_list_append(0, &l2cap_uuid);
1315
apseq = sdp_list_append(0, proto[0]);
1317
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1318
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1319
channel = sdp_data_alloc(SDP_UINT8, &u8);
1320
proto[1] = sdp_list_append(proto[1], channel);
1321
apseq = sdp_list_append(apseq, proto[1]);
1323
aproto = sdp_list_append(0, apseq);
1324
sdp_set_access_protos(&record, aproto);
1326
sdp_set_info_attr(&record, "Fax", 0, 0);
1328
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1329
printf("Service Record registration failed\n");
1333
printf("Fax service registered\n");
1335
sdp_data_free(channel);
1336
sdp_list_free(proto[0], 0);
1337
sdp_list_free(proto[1], 0);
1338
sdp_list_free(apseq, 0);
1339
sdp_list_free(aproto, 0);
1343
static int add_lan(sdp_session_t *session, svc_info_t *si)
1345
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1346
uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
1347
sdp_profile_desc_t profile;
1348
sdp_list_t *aproto, *proto[2];
1349
sdp_record_t record;
1350
uint8_t u8 = si->channel ? si->channel : 4;
1351
sdp_data_t *channel;
1354
memset(&record, 0, sizeof(sdp_record_t));
1355
record.handle = si->handle;
1357
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1358
root = sdp_list_append(0, &root_uuid);
1359
sdp_set_browse_groups(&record, root);
1361
sdp_uuid16_create(&svclass_uuid, LAN_ACCESS_SVCLASS_ID);
1362
svclass_id = sdp_list_append(0, &svclass_uuid);
1363
sdp_set_service_classes(&record, svclass_id);
1365
sdp_uuid16_create(&profile.uuid, LAN_ACCESS_PROFILE_ID);
1366
profile.version = 0x0100;
1367
pfseq = sdp_list_append(0, &profile);
1368
sdp_set_profile_descs(&record, pfseq);
1370
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1371
proto[0] = sdp_list_append(0, &l2cap_uuid);
1372
apseq = sdp_list_append(0, proto[0]);
1374
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1375
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1376
channel = sdp_data_alloc(SDP_UINT8, &u8);
1377
proto[1] = sdp_list_append(proto[1], channel);
1378
apseq = sdp_list_append(apseq, proto[1]);
1380
aproto = sdp_list_append(0, apseq);
1381
sdp_set_access_protos(&record, aproto);
1383
sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0);
1385
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1386
printf("Service Record registration failed\n");
1391
printf("LAN Access service registered\n");
1394
sdp_data_free(channel);
1395
sdp_list_free(proto[0], 0);
1396
sdp_list_free(proto[1], 0);
1397
sdp_list_free(apseq, 0);
1398
sdp_list_free(aproto, 0);
1403
static int add_headset(sdp_session_t *session, svc_info_t *si)
1405
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1406
uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
1407
sdp_profile_desc_t profile;
1408
sdp_list_t *aproto, *proto[2];
1409
sdp_record_t record;
1410
uint8_t u8 = si->channel ? si->channel : 5;
1411
sdp_data_t *channel;
1414
memset(&record, 0, sizeof(sdp_record_t));
1415
record.handle = si->handle;
1417
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1418
root = sdp_list_append(0, &root_uuid);
1419
sdp_set_browse_groups(&record, root);
1421
sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID);
1422
svclass_id = sdp_list_append(0, &svclass_uuid);
1423
sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
1424
svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1425
sdp_set_service_classes(&record, svclass_id);
1427
sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
1428
profile.version = 0x0100;
1429
pfseq = sdp_list_append(0, &profile);
1430
sdp_set_profile_descs(&record, pfseq);
1432
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1433
proto[0] = sdp_list_append(0, &l2cap_uuid);
1434
apseq = sdp_list_append(0, proto[0]);
1436
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1437
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1438
channel = sdp_data_alloc(SDP_UINT8, &u8);
1439
proto[1] = sdp_list_append(proto[1], channel);
1440
apseq = sdp_list_append(apseq, proto[1]);
1442
aproto = sdp_list_append(0, apseq);
1443
sdp_set_access_protos(&record, aproto);
1445
sdp_set_info_attr(&record, "Headset", 0, 0);
1447
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1448
printf("Service Record registration failed\n");
1453
printf("Headset service registered\n");
1456
sdp_data_free(channel);
1457
sdp_list_free(proto[0], 0);
1458
sdp_list_free(proto[1], 0);
1459
sdp_list_free(apseq, 0);
1460
sdp_list_free(aproto, 0);
1465
static int add_headset_ag(sdp_session_t *session, svc_info_t *si)
1467
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1468
uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
1469
sdp_profile_desc_t profile;
1470
sdp_list_t *aproto, *proto[2];
1471
sdp_record_t record;
1472
uint8_t u8 = si->channel ? si->channel : 7;
1473
sdp_data_t *channel;
1474
uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
1475
sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
1478
memset(&record, 0, sizeof(sdp_record_t));
1479
record.handle = si->handle;
1481
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1482
root = sdp_list_append(0, &root_uuid);
1483
sdp_set_browse_groups(&record, root);
1485
sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);
1486
svclass_id = sdp_list_append(0, &svclass_uuid);
1487
sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
1488
svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1489
sdp_set_service_classes(&record, svclass_id);
1491
sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
1492
profile.version = 0x0100;
1493
pfseq = sdp_list_append(0, &profile);
1494
sdp_set_profile_descs(&record, pfseq);
1496
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1497
proto[0] = sdp_list_append(0, &l2cap_uuid);
1498
apseq = sdp_list_append(0, proto[0]);
1500
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1501
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1502
channel = sdp_data_alloc(SDP_UINT8, &u8);
1503
proto[1] = sdp_list_append(proto[1], channel);
1504
apseq = sdp_list_append(apseq, proto[1]);
1506
aproto = sdp_list_append(0, apseq);
1507
sdp_set_access_protos(&record, aproto);
1509
sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
1511
sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
1513
if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
1514
printf("Service Record registration failed\n");
1519
printf("Headset AG service registered\n");
1522
sdp_data_free(channel);
1523
sdp_list_free(proto[0], 0);
1524
sdp_list_free(proto[1], 0);
1525
sdp_list_free(apseq, 0);
1526
sdp_list_free(aproto, 0);
1531
static int add_handsfree(sdp_session_t *session, svc_info_t *si)
1533
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1534
uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
1535
sdp_profile_desc_t profile;
1536
sdp_list_t *aproto, *proto[2];
1537
sdp_record_t record;
1538
uint8_t u8 = si->channel ? si->channel : 6;
1539
uint16_t u16 = 0x31;
1540
sdp_data_t *channel, *features;
1543
memset(&record, 0, sizeof(sdp_record_t));
1544
record.handle = si->handle;
1546
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1547
root = sdp_list_append(0, &root_uuid);
1548
sdp_set_browse_groups(&record, root);
1550
sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID);
1551
svclass_id = sdp_list_append(0, &svclass_uuid);
1552
sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
1553
svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1554
sdp_set_service_classes(&record, svclass_id);
1556
sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
1557
profile.version = 0x0101;
1558
pfseq = sdp_list_append(0, &profile);
1559
sdp_set_profile_descs(&record, pfseq);
1561
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1562
proto[0] = sdp_list_append(0, &l2cap_uuid);
1563
apseq = sdp_list_append(0, proto[0]);
1565
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1566
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1567
channel = sdp_data_alloc(SDP_UINT8, &u8);
1568
proto[1] = sdp_list_append(proto[1], channel);
1569
apseq = sdp_list_append(apseq, proto[1]);
1571
features = sdp_data_alloc(SDP_UINT16, &u16);
1572
sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
1574
aproto = sdp_list_append(0, apseq);
1575
sdp_set_access_protos(&record, aproto);
1577
sdp_set_info_attr(&record, "Handsfree", 0, 0);
1579
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1580
printf("Service Record registration failed\n");
1585
printf("Handsfree service registered\n");
1588
sdp_data_free(channel);
1589
sdp_list_free(proto[0], 0);
1590
sdp_list_free(proto[1], 0);
1591
sdp_list_free(apseq, 0);
1592
sdp_list_free(aproto, 0);
1597
static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si)
1599
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1600
uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
1601
sdp_profile_desc_t profile;
1602
sdp_list_t *aproto, *proto[2];
1603
sdp_record_t record;
1604
uint8_t u8 = si->channel ? si->channel : 7;
1605
uint16_t u16 = 0x17;
1606
sdp_data_t *channel, *features;
1607
uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
1608
sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
1611
memset(&record, 0, sizeof(sdp_record_t));
1612
record.handle = si->handle;
1614
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1615
root = sdp_list_append(0, &root_uuid);
1616
sdp_set_browse_groups(&record, root);
1618
sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
1619
svclass_id = sdp_list_append(0, &svclass_uuid);
1620
sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
1621
svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1622
sdp_set_service_classes(&record, svclass_id);
1624
sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
1625
profile.version = 0x0105;
1626
pfseq = sdp_list_append(0, &profile);
1627
sdp_set_profile_descs(&record, pfseq);
1629
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1630
proto[0] = sdp_list_append(0, &l2cap_uuid);
1631
apseq = sdp_list_append(0, proto[0]);
1633
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1634
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1635
channel = sdp_data_alloc(SDP_UINT8, &u8);
1636
proto[1] = sdp_list_append(proto[1], channel);
1637
apseq = sdp_list_append(apseq, proto[1]);
1639
features = sdp_data_alloc(SDP_UINT16, &u16);
1640
sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
1642
aproto = sdp_list_append(0, apseq);
1643
sdp_set_access_protos(&record, aproto);
1645
sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
1647
sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
1649
if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
1650
printf("Service Record registration failed\n");
1655
printf("Handsfree AG service registered\n");
1658
sdp_data_free(channel);
1659
sdp_list_free(proto[0], 0);
1660
sdp_list_free(proto[1], 0);
1661
sdp_list_free(apseq, 0);
1662
sdp_list_free(aproto, 0);
1667
static int add_simaccess(sdp_session_t *session, svc_info_t *si)
1669
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1670
uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
1671
sdp_profile_desc_t profile;
1672
sdp_list_t *aproto, *proto[2];
1673
sdp_record_t record;
1674
uint8_t u8 = si->channel? si->channel : 8;
1675
uint16_t u16 = 0x31;
1676
sdp_data_t *channel, *features;
1679
memset((void *)&record, 0, sizeof(sdp_record_t));
1680
record.handle = si->handle;
1682
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1683
root = sdp_list_append(0, &root_uuid);
1684
sdp_set_browse_groups(&record, root);
1686
sdp_uuid16_create(&svclass_uuid, SAP_SVCLASS_ID);
1687
svclass_id = sdp_list_append(0, &svclass_uuid);
1688
sdp_uuid16_create(&ga_svclass_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
1689
svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1690
sdp_set_service_classes(&record, svclass_id);
1692
sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID);
1693
profile.version = 0x0101;
1694
pfseq = sdp_list_append(0, &profile);
1695
sdp_set_profile_descs(&record, pfseq);
1697
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1698
proto[0] = sdp_list_append(0, &l2cap_uuid);
1699
apseq = sdp_list_append(0, proto[0]);
1701
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1702
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1703
channel = sdp_data_alloc(SDP_UINT8, &u8);
1704
proto[1] = sdp_list_append(proto[1], channel);
1705
apseq = sdp_list_append(apseq, proto[1]);
1707
features = sdp_data_alloc(SDP_UINT16, &u16);
1708
sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
1710
aproto = sdp_list_append(0, apseq);
1711
sdp_set_access_protos(&record, aproto);
1713
sdp_set_info_attr(&record, "SIM Access", 0, 0);
1715
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1716
printf("Service Record registration failed\n");
1721
printf("SIM Access service registered\n");
1724
sdp_data_free(channel);
1725
sdp_list_free(proto[0], 0);
1726
sdp_list_free(proto[1], 0);
1727
sdp_list_free(apseq, 0);
1728
sdp_list_free(aproto, 0);
1733
static int add_opush(sdp_session_t *session, svc_info_t *si)
1735
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1736
uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
1737
sdp_profile_desc_t profile[1];
1738
sdp_list_t *aproto, *proto[3];
1739
sdp_record_t record;
1740
uint8_t chan = si->channel ? si->channel : 9;
1741
sdp_data_t *channel;
1742
uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xff };
1743
void *dtds[sizeof(formats)], *values[sizeof(formats)];
1745
uint8_t dtd = SDP_UINT8;
1749
memset(&record, 0, sizeof(sdp_record_t));
1750
record.handle = si->handle;
1752
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1753
root = sdp_list_append(0, &root_uuid);
1754
sdp_set_browse_groups(&record, root);
1756
sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
1757
svclass_id = sdp_list_append(0, &opush_uuid);
1758
sdp_set_service_classes(&record, svclass_id);
1760
sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
1761
profile[0].version = 0x0100;
1762
pfseq = sdp_list_append(0, profile);
1763
sdp_set_profile_descs(&record, pfseq);
1765
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1766
proto[0] = sdp_list_append(0, &l2cap_uuid);
1767
apseq = sdp_list_append(0, proto[0]);
1769
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1770
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1771
channel = sdp_data_alloc(SDP_UINT8, &chan);
1772
proto[1] = sdp_list_append(proto[1], channel);
1773
apseq = sdp_list_append(apseq, proto[1]);
1775
sdp_uuid16_create(&obex_uuid, OBEX_UUID);
1776
proto[2] = sdp_list_append(0, &obex_uuid);
1777
apseq = sdp_list_append(apseq, proto[2]);
1779
aproto = sdp_list_append(0, apseq);
1780
sdp_set_access_protos(&record, aproto);
1782
for (i = 0; i < sizeof(formats); i++) {
1784
values[i] = &formats[i];
1786
sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
1787
sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
1789
sdp_set_info_attr(&record, "OBEX Object Push", 0, 0);
1791
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1792
printf("Service Record registration failed\n");
1797
printf("OBEX Object Push service registered\n");
1800
sdp_data_free(channel);
1801
sdp_list_free(proto[0], 0);
1802
sdp_list_free(proto[1], 0);
1803
sdp_list_free(proto[2], 0);
1804
sdp_list_free(apseq, 0);
1805
sdp_list_free(aproto, 0);
1810
static int add_pbap(sdp_session_t *session, svc_info_t *si)
1812
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1813
uuid_t root_uuid, pbap_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
1814
sdp_profile_desc_t profile[1];
1815
sdp_list_t *aproto, *proto[3];
1816
sdp_record_t record;
1817
uint8_t chan = si->channel ? si->channel : 19;
1818
sdp_data_t *channel;
1819
uint8_t formats[] = {0x01};
1820
uint8_t dtd = SDP_UINT8;
1824
memset(&record, 0, sizeof(sdp_record_t));
1825
record.handle = si->handle;
1827
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1828
root = sdp_list_append(0, &root_uuid);
1829
sdp_set_browse_groups(&record, root);
1831
sdp_uuid16_create(&pbap_uuid, PBAP_PSE_SVCLASS_ID);
1832
svclass_id = sdp_list_append(0, &pbap_uuid);
1833
sdp_set_service_classes(&record, svclass_id);
1835
sdp_uuid16_create(&profile[0].uuid, PBAP_PROFILE_ID);
1836
profile[0].version = 0x0100;
1837
pfseq = sdp_list_append(0, profile);
1838
sdp_set_profile_descs(&record, pfseq);
1840
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1841
proto[0] = sdp_list_append(0, &l2cap_uuid);
1842
apseq = sdp_list_append(0, proto[0]);
1844
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1845
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1846
channel = sdp_data_alloc(SDP_UINT8, &chan);
1847
proto[1] = sdp_list_append(proto[1], channel);
1848
apseq = sdp_list_append(apseq, proto[1]);
1850
sdp_uuid16_create(&obex_uuid, OBEX_UUID);
1851
proto[2] = sdp_list_append(0, &obex_uuid);
1852
apseq = sdp_list_append(apseq, proto[2]);
1854
aproto = sdp_list_append(0, apseq);
1855
sdp_set_access_protos(&record, aproto);
1857
sflist = sdp_data_alloc(dtd,formats);
1858
sdp_attr_add(&record, SDP_ATTR_SUPPORTED_REPOSITORIES, sflist);
1860
sdp_set_info_attr(&record, "OBEX Phonebook Access Server", 0, 0);
1862
if (sdp_device_record_register(session, &interface, &record,
1863
SDP_RECORD_PERSIST) < 0) {
1864
printf("Service Record registration failed\n");
1869
printf("PBAP service registered\n");
1872
sdp_data_free(channel);
1873
sdp_list_free(proto[0], 0);
1874
sdp_list_free(proto[1], 0);
1875
sdp_list_free(proto[2], 0);
1876
sdp_list_free(apseq, 0);
1877
sdp_list_free(aproto, 0);
1882
static int add_ftp(sdp_session_t *session, svc_info_t *si)
1884
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1885
uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
1886
sdp_profile_desc_t profile[1];
1887
sdp_list_t *aproto, *proto[3];
1888
sdp_record_t record;
1889
uint8_t u8 = si->channel ? si->channel: 10;
1890
sdp_data_t *channel;
1893
memset(&record, 0, sizeof(sdp_record_t));
1894
record.handle = si->handle;
1896
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1897
root = sdp_list_append(0, &root_uuid);
1898
sdp_set_browse_groups(&record, root);
1900
sdp_uuid16_create(&ftrn_uuid, OBEX_FILETRANS_SVCLASS_ID);
1901
svclass_id = sdp_list_append(0, &ftrn_uuid);
1902
sdp_set_service_classes(&record, svclass_id);
1904
sdp_uuid16_create(&profile[0].uuid, OBEX_FILETRANS_PROFILE_ID);
1905
profile[0].version = 0x0100;
1906
pfseq = sdp_list_append(0, &profile[0]);
1907
sdp_set_profile_descs(&record, pfseq);
1909
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1910
proto[0] = sdp_list_append(0, &l2cap_uuid);
1911
apseq = sdp_list_append(0, proto[0]);
1913
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1914
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1915
channel = sdp_data_alloc(SDP_UINT8, &u8);
1916
proto[1] = sdp_list_append(proto[1], channel);
1917
apseq = sdp_list_append(apseq, proto[1]);
1919
sdp_uuid16_create(&obex_uuid, OBEX_UUID);
1920
proto[2] = sdp_list_append(0, &obex_uuid);
1921
apseq = sdp_list_append(apseq, proto[2]);
1923
aproto = sdp_list_append(0, apseq);
1924
sdp_set_access_protos(&record, aproto);
1926
sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0);
1928
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1929
printf("Service Record registration failed\n");
1934
printf("OBEX File Transfer service registered\n");
1937
sdp_data_free(channel);
1938
sdp_list_free(proto[0], 0);
1939
sdp_list_free(proto[1], 0);
1940
sdp_list_free(proto[2], 0);
1941
sdp_list_free(apseq, 0);
1942
sdp_list_free(aproto, 0);
1947
static int add_directprint(sdp_session_t *session, svc_info_t *si)
1949
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1950
uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
1951
sdp_profile_desc_t profile[1];
1952
sdp_list_t *aproto, *proto[3];
1953
sdp_record_t record;
1954
uint8_t chan = si->channel ? si->channel : 12;
1955
sdp_data_t *channel;
1958
memset(&record, 0, sizeof(sdp_record_t));
1959
record.handle = si->handle;
1961
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1962
root = sdp_list_append(0, &root_uuid);
1963
sdp_set_browse_groups(&record, root);
1965
sdp_uuid16_create(&opush_uuid, DIRECT_PRINTING_SVCLASS_ID);
1966
svclass_id = sdp_list_append(0, &opush_uuid);
1967
sdp_set_service_classes(&record, svclass_id);
1969
sdp_uuid16_create(&profile[0].uuid, BASIC_PRINTING_PROFILE_ID);
1970
profile[0].version = 0x0100;
1971
pfseq = sdp_list_append(0, profile);
1972
sdp_set_profile_descs(&record, pfseq);
1974
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1975
proto[0] = sdp_list_append(0, &l2cap_uuid);
1976
apseq = sdp_list_append(0, proto[0]);
1978
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1979
proto[1] = sdp_list_append(0, &rfcomm_uuid);
1980
channel = sdp_data_alloc(SDP_UINT8, &chan);
1981
proto[1] = sdp_list_append(proto[1], channel);
1982
apseq = sdp_list_append(apseq, proto[1]);
1984
sdp_uuid16_create(&obex_uuid, OBEX_UUID);
1985
proto[2] = sdp_list_append(0, &obex_uuid);
1986
apseq = sdp_list_append(apseq, proto[2]);
1988
aproto = sdp_list_append(0, apseq);
1989
sdp_set_access_protos(&record, aproto);
1991
sdp_set_info_attr(&record, "Direct Printing", 0, 0);
1993
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1994
printf("Service Record registration failed\n");
1999
printf("Direct Printing service registered\n");
2002
sdp_data_free(channel);
2003
sdp_list_free(proto[0], 0);
2004
sdp_list_free(proto[1], 0);
2005
sdp_list_free(proto[2], 0);
2006
sdp_list_free(apseq, 0);
2007
sdp_list_free(aproto, 0);
2012
static int add_nap(sdp_session_t *session, svc_info_t *si)
2014
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2015
uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
2016
sdp_profile_desc_t profile[1];
2017
sdp_list_t *aproto, *proto[2];
2018
sdp_record_t record;
2019
uint16_t lp = 0x000f, ver = 0x0100;
2020
sdp_data_t *psm, *version;
2023
memset(&record, 0, sizeof(sdp_record_t));
2024
record.handle = si->handle;
2026
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2027
root = sdp_list_append(0, &root_uuid);
2028
sdp_set_browse_groups(&record, root);
2030
sdp_uuid16_create(&ftrn_uuid, NAP_SVCLASS_ID);
2031
svclass_id = sdp_list_append(0, &ftrn_uuid);
2032
sdp_set_service_classes(&record, svclass_id);
2034
sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
2035
profile[0].version = 0x0100;
2036
pfseq = sdp_list_append(0, &profile[0]);
2037
sdp_set_profile_descs(&record, pfseq);
2039
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2040
proto[0] = sdp_list_append(0, &l2cap_uuid);
2041
psm = sdp_data_alloc(SDP_UINT16, &lp);
2042
proto[0] = sdp_list_append(proto[0], psm);
2043
apseq = sdp_list_append(0, proto[0]);
2045
sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
2046
proto[1] = sdp_list_append(0, &bnep_uuid);
2047
version = sdp_data_alloc(SDP_UINT16, &ver);
2048
proto[1] = sdp_list_append(proto[1], version);
2051
uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 };
2052
sdp_data_t *head, *pseq;
2055
for (p = 0, head = NULL; p < 4; p++) {
2056
sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
2057
head = sdp_seq_append(head, data);
2059
pseq = sdp_data_alloc(SDP_SEQ16, head);
2060
proto[1] = sdp_list_append(proto[1], pseq);
2063
apseq = sdp_list_append(apseq, proto[1]);
2065
aproto = sdp_list_append(0, apseq);
2066
sdp_set_access_protos(&record, aproto);
2068
sdp_set_info_attr(&record, "Network Access Point Service", 0, 0);
2070
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2071
printf("Service Record registration failed\n");
2076
printf("NAP service registered\n");
2079
sdp_data_free(version);
2081
sdp_list_free(proto[0], 0);
2082
sdp_list_free(proto[1], 0);
2083
sdp_list_free(apseq, 0);
2084
sdp_list_free(aproto, 0);
2089
static int add_gn(sdp_session_t *session, svc_info_t *si)
2091
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2092
uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
2093
sdp_profile_desc_t profile[1];
2094
sdp_list_t *aproto, *proto[2];
2095
sdp_record_t record;
2096
uint16_t lp = 0x000f, ver = 0x0100;
2097
sdp_data_t *psm, *version;
2100
memset(&record, 0, sizeof(sdp_record_t));
2101
record.handle = si->handle;
2103
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2104
root = sdp_list_append(0, &root_uuid);
2105
sdp_set_browse_groups(&record, root);
2107
sdp_uuid16_create(&ftrn_uuid, GN_SVCLASS_ID);
2108
svclass_id = sdp_list_append(0, &ftrn_uuid);
2109
sdp_set_service_classes(&record, svclass_id);
2111
sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID);
2112
profile[0].version = 0x0100;
2113
pfseq = sdp_list_append(0, &profile[0]);
2114
sdp_set_profile_descs(&record, pfseq);
2116
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2117
proto[0] = sdp_list_append(0, &l2cap_uuid);
2118
psm = sdp_data_alloc(SDP_UINT16, &lp);
2119
proto[0] = sdp_list_append(proto[0], psm);
2120
apseq = sdp_list_append(0, proto[0]);
2122
sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
2123
proto[1] = sdp_list_append(0, &bnep_uuid);
2124
version = sdp_data_alloc(SDP_UINT16, &ver);
2125
proto[1] = sdp_list_append(proto[1], version);
2126
apseq = sdp_list_append(apseq, proto[1]);
2128
aproto = sdp_list_append(0, apseq);
2129
sdp_set_access_protos(&record, aproto);
2131
sdp_set_info_attr(&record, "Group Network Service", 0, 0);
2133
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2134
printf("Service Record registration failed\n");
2139
printf("GN service registered\n");
2142
sdp_data_free(version);
2144
sdp_list_free(proto[0], 0);
2145
sdp_list_free(proto[1], 0);
2146
sdp_list_free(apseq, 0);
2147
sdp_list_free(aproto, 0);
2152
static int add_panu(sdp_session_t *session, svc_info_t *si)
2154
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2155
uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
2156
sdp_profile_desc_t profile[1];
2157
sdp_list_t *aproto, *proto[2];
2158
sdp_record_t record;
2159
uint16_t lp = 0x000f, ver = 0x0100;
2160
sdp_data_t *psm, *version;
2163
memset(&record, 0, sizeof(sdp_record_t));
2164
record.handle = si->handle;
2166
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2167
root = sdp_list_append(NULL, &root_uuid);
2168
sdp_set_browse_groups(&record, root);
2169
sdp_list_free(root, NULL);
2171
sdp_uuid16_create(&ftrn_uuid, PANU_SVCLASS_ID);
2172
svclass_id = sdp_list_append(NULL, &ftrn_uuid);
2173
sdp_set_service_classes(&record, svclass_id);
2174
sdp_list_free(svclass_id, NULL);
2176
sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
2177
profile[0].version = 0x0100;
2178
pfseq = sdp_list_append(NULL, &profile[0]);
2179
sdp_set_profile_descs(&record, pfseq);
2180
sdp_list_free(pfseq, NULL);
2182
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2183
proto[0] = sdp_list_append(NULL, &l2cap_uuid);
2184
psm = sdp_data_alloc(SDP_UINT16, &lp);
2185
proto[0] = sdp_list_append(proto[0], psm);
2186
apseq = sdp_list_append(NULL, proto[0]);
2188
sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
2189
proto[1] = sdp_list_append(NULL, &bnep_uuid);
2190
version = sdp_data_alloc(SDP_UINT16, &ver);
2191
proto[1] = sdp_list_append(proto[1], version);
2192
apseq = sdp_list_append(apseq, proto[1]);
2194
aproto = sdp_list_append(NULL, apseq);
2195
sdp_set_access_protos(&record, aproto);
2197
sdp_set_info_attr(&record, "PAN User", NULL, NULL);
2199
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2200
printf("Service Record registration failed\n");
2205
printf("PANU service registered\n");
2208
sdp_data_free(version);
2210
sdp_list_free(proto[0], 0);
2211
sdp_list_free(proto[1], 0);
2212
sdp_list_free(apseq, 0);
2213
sdp_list_free(aproto, 0);
2218
static int add_hid_keyb(sdp_session_t *session, svc_info_t *si)
2220
sdp_record_t record;
2221
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2222
uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid;
2223
sdp_profile_desc_t profile[1];
2224
sdp_list_t *aproto, *proto[3];
2225
sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
2227
uint8_t dtd = SDP_UINT16;
2228
uint8_t dtd2 = SDP_UINT8;
2229
uint8_t dtd_data = SDP_TEXT_STR8;
2235
uint8_t hid_spec_type = 0x22;
2236
uint16_t hid_attr_lang[] = { 0x409, 0x100 };
2237
static const uint16_t ctrl = 0x11;
2238
static const uint16_t intr = 0x13;
2239
static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 };
2240
static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 };
2241
const uint8_t hid_spec[] = {
2242
0x05, 0x01, // usage page
2243
0x09, 0x06, // keyboard
2244
0xa1, 0x01, // key codes
2245
0x85, 0x01, // minimum
2247
0x19, 0xe0, // logical min
2248
0x29, 0xe7, // logical max
2249
0x15, 0x00, // report size
2250
0x25, 0x01, // report count
2251
0x75, 0x01, // input data variable absolute
2252
0x95, 0x08, // report count
2253
0x81, 0x02, // report size
2294
memset(&record, 0, sizeof(sdp_record_t));
2295
record.handle = si->handle;
2297
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2298
root = sdp_list_append(0, &root_uuid);
2299
sdp_set_browse_groups(&record, root);
2301
sdp_add_lang_attr(&record);
2303
sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
2304
svclass_id = sdp_list_append(0, &hidkb_uuid);
2305
sdp_set_service_classes(&record, svclass_id);
2307
sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
2308
profile[0].version = 0x0100;
2309
pfseq = sdp_list_append(0, profile);
2310
sdp_set_profile_descs(&record, pfseq);
2313
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2314
proto[1] = sdp_list_append(0, &l2cap_uuid);
2315
psm = sdp_data_alloc(SDP_UINT16, &ctrl);
2316
proto[1] = sdp_list_append(proto[1], psm);
2317
apseq = sdp_list_append(0, proto[1]);
2319
sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2320
proto[2] = sdp_list_append(0, &hidp_uuid);
2321
apseq = sdp_list_append(apseq, proto[2]);
2323
aproto = sdp_list_append(0, apseq);
2324
sdp_set_access_protos(&record, aproto);
2326
/* additional protocols */
2327
proto[1] = sdp_list_append(0, &l2cap_uuid);
2328
psm = sdp_data_alloc(SDP_UINT16, &intr);
2329
proto[1] = sdp_list_append(proto[1], psm);
2330
apseq = sdp_list_append(0, proto[1]);
2332
sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2333
proto[2] = sdp_list_append(0, &hidp_uuid);
2334
apseq = sdp_list_append(apseq, proto[2]);
2336
aproto = sdp_list_append(0, apseq);
2337
sdp_set_add_access_protos(&record, aproto);
2339
sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL);
2341
for (i = 0; i < sizeof(hid_attr) / 2; i++)
2342
sdp_attr_add_new(&record,
2343
SDP_ATTR_HID_DEVICE_RELEASE_NUMBER + i,
2344
SDP_UINT16, &hid_attr[i]);
2347
values[0] = &hid_spec_type;
2348
dtds[1] = &dtd_data;
2349
values[1] = (uint8_t *) hid_spec;
2351
leng[1] = sizeof(hid_spec);
2352
hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
2353
hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
2354
sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
2356
for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
2358
values2[i] = &hid_attr_lang[i];
2361
lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
2362
lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
2363
sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
2365
sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]);
2367
for (i = 0; i < sizeof(hid_attr2) / 2 - 1; i++)
2368
sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP + i,
2369
SDP_UINT16, &hid_attr2[i + 1]);
2371
if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
2372
printf("Service Record registration failed\n");
2376
printf("HID keyboard service registered\n");
2381
static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si)
2383
sdp_record_t record;
2384
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2385
uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid;
2386
sdp_profile_desc_t profile[1];
2387
sdp_list_t *aproto, *proto[3];
2388
sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
2390
uint8_t dtd = SDP_UINT16;
2391
uint8_t dtd2 = SDP_UINT8;
2392
uint8_t dtd_data = SDP_TEXT_STR8;
2398
uint8_t hid_spec_type = 0x22;
2399
uint16_t hid_attr_lang[] = { 0x409, 0x100 };
2400
uint16_t ctrl = 0x11, intr = 0x13;
2401
uint16_t hid_release = 0x0100, parser_version = 0x0111;
2402
uint8_t subclass = 0x04, country = 0x33;
2403
uint8_t virtual_cable = 0, reconnect = 1, sdp_disable = 0;
2404
uint8_t battery = 1, remote_wakeup = 1;
2405
uint16_t profile_version = 0x0100, superv_timeout = 0x0c80;
2406
uint8_t norm_connect = 0, boot_device = 0;
2407
const uint8_t hid_spec[] = {
2408
0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10,
2409
0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
2410
0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00,
2411
0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2412
0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00,
2413
0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2414
0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2415
0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2416
0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
2417
0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00,
2418
0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
2419
0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2420
0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2421
0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00,
2422
0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2423
0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00,
2424
0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00,
2425
0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00,
2426
0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00,
2427
0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00,
2428
0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2429
0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2430
0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2431
0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2432
0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2433
0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2434
0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2438
memset(&record, 0, sizeof(sdp_record_t));
2439
record.handle = si->handle;
2441
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2442
root = sdp_list_append(NULL, &root_uuid);
2443
sdp_set_browse_groups(&record, root);
2445
sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID);
2446
svclass_id = sdp_list_append(NULL, &hid_uuid);
2447
sdp_set_service_classes(&record, svclass_id);
2449
sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
2450
profile[0].version = 0x0100;
2451
pfseq = sdp_list_append(NULL, profile);
2452
sdp_set_profile_descs(&record, pfseq);
2454
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2455
proto[1] = sdp_list_append(0, &l2cap_uuid);
2456
psm = sdp_data_alloc(SDP_UINT16, &ctrl);
2457
proto[1] = sdp_list_append(proto[1], psm);
2458
apseq = sdp_list_append(0, proto[1]);
2460
sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2461
proto[2] = sdp_list_append(0, &hidp_uuid);
2462
apseq = sdp_list_append(apseq, proto[2]);
2464
aproto = sdp_list_append(0, apseq);
2465
sdp_set_access_protos(&record, aproto);
2467
proto[1] = sdp_list_append(0, &l2cap_uuid);
2468
psm = sdp_data_alloc(SDP_UINT16, &intr);
2469
proto[1] = sdp_list_append(proto[1], psm);
2470
apseq = sdp_list_append(0, proto[1]);
2472
sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2473
proto[2] = sdp_list_append(0, &hidp_uuid);
2474
apseq = sdp_list_append(apseq, proto[2]);
2476
aproto = sdp_list_append(0, apseq);
2477
sdp_set_add_access_protos(&record, aproto);
2479
sdp_add_lang_attr(&record);
2481
sdp_set_info_attr(&record, "Nintendo RVL-CNT-01",
2482
"Nintendo", "Nintendo RVL-CNT-01");
2484
sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
2485
SDP_UINT16, &hid_release);
2487
sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION,
2488
SDP_UINT16, &parser_version);
2490
sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS,
2491
SDP_UINT8, &subclass);
2493
sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE,
2494
SDP_UINT8, &country);
2496
sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE,
2497
SDP_BOOL, &virtual_cable);
2499
sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE,
2500
SDP_BOOL, &reconnect);
2503
values[0] = &hid_spec_type;
2504
dtds[1] = &dtd_data;
2505
values[1] = (uint8_t *) hid_spec;
2507
leng[1] = sizeof(hid_spec);
2508
hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
2509
hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
2510
sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
2512
for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
2514
values2[i] = &hid_attr_lang[i];
2517
lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
2518
lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
2519
sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
2521
sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE,
2522
SDP_BOOL, &sdp_disable);
2524
sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER,
2525
SDP_BOOL, &battery);
2527
sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP,
2528
SDP_BOOL, &remote_wakeup);
2530
sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION,
2531
SDP_UINT16, &profile_version);
2533
sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT,
2534
SDP_UINT16, &superv_timeout);
2536
sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE,
2537
SDP_BOOL, &norm_connect);
2539
sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE,
2540
SDP_BOOL, &boot_device);
2542
if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
2543
printf("Service Record registration failed\n");
2547
printf("Wii-Mote service registered\n");
2552
static int add_cip(sdp_session_t *session, svc_info_t *si)
2554
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2555
uuid_t root_uuid, l2cap, cmtp, cip;
2556
sdp_profile_desc_t profile[1];
2557
sdp_list_t *aproto, *proto[2];
2558
sdp_record_t record;
2559
uint16_t psm = si->psm ? si->psm : 0x1001;
2560
uint8_t netid = si->network ? si->network : 0x02; // 0x02 = ISDN, 0x03 = GSM
2561
sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
2564
memset(&record, 0, sizeof(sdp_record_t));
2565
record.handle = si->handle;
2567
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2568
root = sdp_list_append(0, &root_uuid);
2569
sdp_set_browse_groups(&record, root);
2571
sdp_uuid16_create(&cip, CIP_SVCLASS_ID);
2572
svclass_id = sdp_list_append(0, &cip);
2573
sdp_set_service_classes(&record, svclass_id);
2575
sdp_uuid16_create(&profile[0].uuid, CIP_PROFILE_ID);
2576
profile[0].version = 0x0100;
2577
pfseq = sdp_list_append(0, &profile[0]);
2578
sdp_set_profile_descs(&record, pfseq);
2580
sdp_uuid16_create(&l2cap, L2CAP_UUID);
2581
proto[0] = sdp_list_append(0, &l2cap);
2582
apseq = sdp_list_append(0, proto[0]);
2583
proto[0] = sdp_list_append(proto[0], sdp_data_alloc(SDP_UINT16, &psm));
2584
apseq = sdp_list_append(0, proto[0]);
2586
sdp_uuid16_create(&cmtp, CMTP_UUID);
2587
proto[1] = sdp_list_append(0, &cmtp);
2588
apseq = sdp_list_append(apseq, proto[1]);
2590
aproto = sdp_list_append(0, apseq);
2591
sdp_set_access_protos(&record, aproto);
2593
sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
2595
sdp_set_info_attr(&record, "Common ISDN Access", 0, 0);
2597
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2598
printf("Service Record registration failed\n");
2603
printf("CIP service registered\n");
2606
sdp_list_free(proto[0], 0);
2607
sdp_list_free(proto[1], 0);
2608
sdp_list_free(apseq, 0);
2609
sdp_list_free(aproto, 0);
2610
sdp_data_free(network);
2615
static int add_ctp(sdp_session_t *session, svc_info_t *si)
2617
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2618
uuid_t root_uuid, l2cap, tcsbin, ctp;
2619
sdp_profile_desc_t profile[1];
2620
sdp_list_t *aproto, *proto[2];
2621
sdp_record_t record;
2622
uint8_t netid = si->network ? si->network : 0x02; // 0x01-0x07 cf. p120 profile document
2623
sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
2626
memset(&record, 0, sizeof(sdp_record_t));
2627
record.handle = si->handle;
2629
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2630
root = sdp_list_append(0, &root_uuid);
2631
sdp_set_browse_groups(&record, root);
2633
sdp_uuid16_create(&ctp, CORDLESS_TELEPHONY_SVCLASS_ID);
2634
svclass_id = sdp_list_append(0, &ctp);
2635
sdp_set_service_classes(&record, svclass_id);
2637
sdp_uuid16_create(&profile[0].uuid, CORDLESS_TELEPHONY_PROFILE_ID);
2638
profile[0].version = 0x0100;
2639
pfseq = sdp_list_append(0, &profile[0]);
2640
sdp_set_profile_descs(&record, pfseq);
2642
sdp_uuid16_create(&l2cap, L2CAP_UUID);
2643
proto[0] = sdp_list_append(0, &l2cap);
2644
apseq = sdp_list_append(0, proto[0]);
2646
sdp_uuid16_create(&tcsbin, TCS_BIN_UUID);
2647
proto[1] = sdp_list_append(0, &tcsbin);
2648
apseq = sdp_list_append(apseq, proto[1]);
2650
aproto = sdp_list_append(0, apseq);
2651
sdp_set_access_protos(&record, aproto);
2653
sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
2655
sdp_set_info_attr(&record, "Cordless Telephony", 0, 0);
2657
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2658
printf("Service Record registration failed\n");
2663
printf("CTP service registered\n");
2666
sdp_list_free(proto[0], 0);
2667
sdp_list_free(proto[1], 0);
2668
sdp_list_free(apseq, 0);
2669
sdp_list_free(aproto, 0);
2670
sdp_data_free(network);
2675
static int add_a2source(sdp_session_t *session, svc_info_t *si)
2677
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2678
uuid_t root_uuid, l2cap, avdtp, a2src;
2679
sdp_profile_desc_t profile[1];
2680
sdp_list_t *aproto, *proto[2];
2681
sdp_record_t record;
2682
sdp_data_t *psm, *version;
2683
uint16_t lp = 0x0019, ver = 0x0100;
2686
memset(&record, 0, sizeof(sdp_record_t));
2687
record.handle = si->handle;
2689
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2690
root = sdp_list_append(0, &root_uuid);
2691
sdp_set_browse_groups(&record, root);
2693
sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
2694
svclass_id = sdp_list_append(0, &a2src);
2695
sdp_set_service_classes(&record, svclass_id);
2697
sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
2698
profile[0].version = 0x0100;
2699
pfseq = sdp_list_append(0, &profile[0]);
2700
sdp_set_profile_descs(&record, pfseq);
2702
sdp_uuid16_create(&l2cap, L2CAP_UUID);
2703
proto[0] = sdp_list_append(0, &l2cap);
2704
psm = sdp_data_alloc(SDP_UINT16, &lp);
2705
proto[0] = sdp_list_append(proto[0], psm);
2706
apseq = sdp_list_append(0, proto[0]);
2708
sdp_uuid16_create(&avdtp, AVDTP_UUID);
2709
proto[1] = sdp_list_append(0, &avdtp);
2710
version = sdp_data_alloc(SDP_UINT16, &ver);
2711
proto[1] = sdp_list_append(proto[1], version);
2712
apseq = sdp_list_append(apseq, proto[1]);
2714
aproto = sdp_list_append(0, apseq);
2715
sdp_set_access_protos(&record, aproto);
2717
sdp_set_info_attr(&record, "Audio Source", 0, 0);
2719
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2720
printf("Service Record registration failed\n");
2725
printf("Audio source service registered\n");
2728
sdp_list_free(proto[0], 0);
2729
sdp_list_free(proto[1], 0);
2730
sdp_list_free(apseq, 0);
2731
sdp_list_free(aproto, 0);
2736
static int add_a2sink(sdp_session_t *session, svc_info_t *si)
2738
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2739
uuid_t root_uuid, l2cap, avdtp, a2snk;
2740
sdp_profile_desc_t profile[1];
2741
sdp_list_t *aproto, *proto[2];
2742
sdp_record_t record;
2743
sdp_data_t *psm, *version;
2744
uint16_t lp = 0x0019, ver = 0x0100;
2747
memset(&record, 0, sizeof(sdp_record_t));
2748
record.handle = si->handle;
2750
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2751
root = sdp_list_append(0, &root_uuid);
2752
sdp_set_browse_groups(&record, root);
2754
sdp_uuid16_create(&a2snk, AUDIO_SINK_SVCLASS_ID);
2755
svclass_id = sdp_list_append(0, &a2snk);
2756
sdp_set_service_classes(&record, svclass_id);
2758
sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
2759
profile[0].version = 0x0100;
2760
pfseq = sdp_list_append(0, &profile[0]);
2761
sdp_set_profile_descs(&record, pfseq);
2763
sdp_uuid16_create(&l2cap, L2CAP_UUID);
2764
proto[0] = sdp_list_append(0, &l2cap);
2765
psm = sdp_data_alloc(SDP_UINT16, &lp);
2766
proto[0] = sdp_list_append(proto[0], psm);
2767
apseq = sdp_list_append(0, proto[0]);
2769
sdp_uuid16_create(&avdtp, AVDTP_UUID);
2770
proto[1] = sdp_list_append(0, &avdtp);
2771
version = sdp_data_alloc(SDP_UINT16, &ver);
2772
proto[1] = sdp_list_append(proto[1], version);
2773
apseq = sdp_list_append(apseq, proto[1]);
2775
aproto = sdp_list_append(0, apseq);
2776
sdp_set_access_protos(&record, aproto);
2778
sdp_set_info_attr(&record, "Audio Sink", 0, 0);
2780
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2781
printf("Service Record registration failed\n");
2786
printf("Audio sink service registered\n");
2789
sdp_list_free(proto[0], 0);
2790
sdp_list_free(proto[1], 0);
2791
sdp_list_free(apseq, 0);
2792
sdp_list_free(aproto, 0);
2797
static int add_avrct(sdp_session_t *session, svc_info_t *si)
2799
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2800
uuid_t root_uuid, l2cap, avctp, avrct;
2801
sdp_profile_desc_t profile[1];
2802
sdp_list_t *aproto, *proto[2];
2803
sdp_record_t record;
2804
sdp_data_t *psm, *version, *features;
2805
uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
2808
memset(&record, 0, sizeof(sdp_record_t));
2809
record.handle = si->handle;
2811
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2812
root = sdp_list_append(0, &root_uuid);
2813
sdp_set_browse_groups(&record, root);
2815
sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);
2816
svclass_id = sdp_list_append(0, &avrct);
2817
sdp_set_service_classes(&record, svclass_id);
2819
sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
2820
profile[0].version = 0x0100;
2821
pfseq = sdp_list_append(0, &profile[0]);
2822
sdp_set_profile_descs(&record, pfseq);
2824
sdp_uuid16_create(&l2cap, L2CAP_UUID);
2825
proto[0] = sdp_list_append(0, &l2cap);
2826
psm = sdp_data_alloc(SDP_UINT16, &lp);
2827
proto[0] = sdp_list_append(proto[0], psm);
2828
apseq = sdp_list_append(0, proto[0]);
2830
sdp_uuid16_create(&avctp, AVCTP_UUID);
2831
proto[1] = sdp_list_append(0, &avctp);
2832
version = sdp_data_alloc(SDP_UINT16, &ver);
2833
proto[1] = sdp_list_append(proto[1], version);
2834
apseq = sdp_list_append(apseq, proto[1]);
2836
aproto = sdp_list_append(0, apseq);
2837
sdp_set_access_protos(&record, aproto);
2839
features = sdp_data_alloc(SDP_UINT16, &feat);
2840
sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
2842
sdp_set_info_attr(&record, "AVRCP CT", 0, 0);
2844
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2845
printf("Service Record registration failed\n");
2850
printf("Remote control service registered\n");
2853
sdp_list_free(proto[0], 0);
2854
sdp_list_free(proto[1], 0);
2855
sdp_list_free(apseq, 0);
2856
sdp_list_free(aproto, 0);
2861
static int add_avrtg(sdp_session_t *session, svc_info_t *si)
2863
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2864
uuid_t root_uuid, l2cap, avctp, avrtg;
2865
sdp_profile_desc_t profile[1];
2866
sdp_list_t *aproto, *proto[2];
2867
sdp_record_t record;
2868
sdp_data_t *psm, *version, *features;
2869
uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
2872
memset(&record, 0, sizeof(sdp_record_t));
2873
record.handle = si->handle;
2875
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2876
root = sdp_list_append(0, &root_uuid);
2877
sdp_set_browse_groups(&record, root);
2879
sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
2880
svclass_id = sdp_list_append(0, &avrtg);
2881
sdp_set_service_classes(&record, svclass_id);
2883
sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
2884
profile[0].version = 0x0100;
2885
pfseq = sdp_list_append(0, &profile[0]);
2886
sdp_set_profile_descs(&record, pfseq);
2888
sdp_uuid16_create(&l2cap, L2CAP_UUID);
2889
proto[0] = sdp_list_append(0, &l2cap);
2890
psm = sdp_data_alloc(SDP_UINT16, &lp);
2891
proto[0] = sdp_list_append(proto[0], psm);
2892
apseq = sdp_list_append(0, proto[0]);
2894
sdp_uuid16_create(&avctp, AVCTP_UUID);
2895
proto[1] = sdp_list_append(0, &avctp);
2896
version = sdp_data_alloc(SDP_UINT16, &ver);
2897
proto[1] = sdp_list_append(proto[1], version);
2898
apseq = sdp_list_append(apseq, proto[1]);
2900
aproto = sdp_list_append(0, apseq);
2901
sdp_set_access_protos(&record, aproto);
2903
features = sdp_data_alloc(SDP_UINT16, &feat);
2904
sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
2906
sdp_set_info_attr(&record, "AVRCP TG", 0, 0);
2908
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2909
printf("Service Record registration failed\n");
2914
printf("Remote target service registered\n");
2917
sdp_list_free(proto[0], 0);
2918
sdp_list_free(proto[1], 0);
2919
sdp_list_free(apseq, 0);
2920
sdp_list_free(aproto, 0);
2925
static int add_udi_ue(sdp_session_t *session, svc_info_t *si)
2927
sdp_record_t record;
2928
sdp_list_t *root, *svclass, *proto;
2929
uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
2930
uint8_t channel = si->channel ? si->channel: 18;
2932
memset(&record, 0, sizeof(record));
2933
record.handle = si->handle;
2935
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2936
root = sdp_list_append(NULL, &root_uuid);
2937
sdp_set_browse_groups(&record, root);
2938
sdp_list_free(root, NULL);
2940
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2941
proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
2943
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
2944
proto = sdp_list_append(proto, sdp_list_append(
2945
sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
2947
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
2949
sdp_uuid16_create(&svclass_uuid, UDI_MT_SVCLASS_ID);
2950
svclass = sdp_list_append(NULL, &svclass_uuid);
2951
sdp_set_service_classes(&record, svclass);
2952
sdp_list_free(svclass, NULL);
2954
sdp_set_info_attr(&record, "UDI UE", NULL, NULL);
2956
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2957
printf("Service Record registration failed\n");
2961
printf("UDI UE service registered\n");
2966
static int add_udi_te(sdp_session_t *session, svc_info_t *si)
2968
sdp_record_t record;
2969
sdp_list_t *root, *svclass, *proto;
2970
uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
2971
uint8_t channel = si->channel ? si->channel: 19;
2973
memset(&record, 0, sizeof(record));
2974
record.handle = si->handle;
2976
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2977
root = sdp_list_append(NULL, &root_uuid);
2978
sdp_set_browse_groups(&record, root);
2979
sdp_list_free(root, NULL);
2981
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2982
proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
2984
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
2985
proto = sdp_list_append(proto, sdp_list_append(
2986
sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
2988
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
2990
sdp_uuid16_create(&svclass_uuid, UDI_TA_SVCLASS_ID);
2991
svclass = sdp_list_append(NULL, &svclass_uuid);
2992
sdp_set_service_classes(&record, svclass);
2993
sdp_list_free(svclass, NULL);
2995
sdp_set_info_attr(&record, "UDI TE", NULL, NULL);
2997
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2998
printf("Service Record registration failed\n");
3002
printf("UDI TE service registered\n");
3007
static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0,
3008
0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 };
3010
static int add_sr1(sdp_session_t *session, svc_info_t *si)
3012
sdp_record_t record;
3013
sdp_list_t *root, *svclass;
3014
uuid_t root_uuid, svclass_uuid;
3016
memset(&record, 0, sizeof(record));
3017
record.handle = si->handle;
3019
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3020
root = sdp_list_append(NULL, &root_uuid);
3021
sdp_set_browse_groups(&record, root);
3023
sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid);
3024
svclass = sdp_list_append(NULL, &svclass_uuid);
3025
sdp_set_service_classes(&record, svclass);
3027
sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL);
3029
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3030
printf("Service Record registration failed\n");
3034
printf("Toshiba Speech Recognition SR-1 service record registered\n");
3039
static unsigned char syncmls_uuid[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
3040
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
3042
static unsigned char syncmlc_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
3043
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
3045
static int add_syncml(sdp_session_t *session, svc_info_t *si)
3047
sdp_record_t record;
3048
sdp_list_t *root, *svclass, *proto;
3049
uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
3050
uint8_t channel = si->channel ? si->channel: 15;
3052
memset(&record, 0, sizeof(record));
3053
record.handle = si->handle;
3055
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3056
root = sdp_list_append(NULL, &root_uuid);
3057
sdp_set_browse_groups(&record, root);
3059
sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid);
3060
svclass = sdp_list_append(NULL, &svclass_uuid);
3061
sdp_set_service_classes(&record, svclass);
3063
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3064
proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3066
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3067
proto = sdp_list_append(proto, sdp_list_append(
3068
sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3070
sdp_uuid16_create(&obex_uuid, OBEX_UUID);
3071
proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid));
3073
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3075
sdp_set_info_attr(&record, "SyncML Client", NULL, NULL);
3077
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3078
printf("Service Record registration failed\n");
3082
printf("SyncML Client service record registered\n");
3087
static unsigned char async_uuid[] = { 0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62,
3088
0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C };
3090
static int add_activesync(sdp_session_t *session, svc_info_t *si)
3092
sdp_record_t record;
3093
sdp_list_t *root, *svclass, *proto;
3094
uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
3095
uint8_t channel = si->channel ? si->channel: 21;
3097
memset(&record, 0, sizeof(record));
3098
record.handle = si->handle;
3100
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3101
root = sdp_list_append(NULL, &root_uuid);
3102
sdp_set_browse_groups(&record, root);
3104
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3105
proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3107
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3108
proto = sdp_list_append(proto, sdp_list_append(
3109
sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3111
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3113
sdp_uuid128_create(&svclass_uuid, (void *) async_uuid);
3114
svclass = sdp_list_append(NULL, &svclass_uuid);
3115
sdp_set_service_classes(&record, svclass);
3117
sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL);
3119
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3120
printf("Service Record registration failed\n");
3124
printf("ActiveSync service record registered\n");
3129
static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
3130
0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
3132
static int add_hotsync(sdp_session_t *session, svc_info_t *si)
3134
sdp_record_t record;
3135
sdp_list_t *root, *svclass, *proto;
3136
uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
3137
uint8_t channel = si->channel ? si->channel: 22;
3139
memset(&record, 0, sizeof(record));
3140
record.handle = si->handle;
3142
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3143
root = sdp_list_append(NULL, &root_uuid);
3144
sdp_set_browse_groups(&record, root);
3146
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3147
proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3149
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3150
proto = sdp_list_append(proto, sdp_list_append(
3151
sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3153
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3155
sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
3156
svclass = sdp_list_append(NULL, &svclass_uuid);
3157
sdp_set_service_classes(&record, svclass);
3159
sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
3161
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3162
printf("Service Record registration failed\n");
3166
printf("HotSync service record registered\n");
3171
static unsigned char palmos_uuid[] = { 0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51,
3172
0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 };
3174
static int add_palmos(sdp_session_t *session, svc_info_t *si)
3176
sdp_record_t record;
3177
sdp_list_t *root, *svclass;
3178
uuid_t root_uuid, svclass_uuid;
3180
memset(&record, 0, sizeof(record));
3181
record.handle = si->handle;
3183
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3184
root = sdp_list_append(NULL, &root_uuid);
3185
sdp_set_browse_groups(&record, root);
3187
sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid);
3188
svclass = sdp_list_append(NULL, &svclass_uuid);
3189
sdp_set_service_classes(&record, svclass);
3191
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3192
printf("Service Record registration failed\n");
3196
printf("PalmOS service record registered\n");
3201
static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00,
3202
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3204
static int add_nokiaid(sdp_session_t *session, svc_info_t *si)
3206
sdp_record_t record;
3207
sdp_list_t *root, *svclass;
3208
uuid_t root_uuid, svclass_uuid;
3209
uint16_t verid = 0x005f;
3210
sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid);
3212
memset(&record, 0, sizeof(record));
3213
record.handle = si->handle;
3215
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3216
root = sdp_list_append(NULL, &root_uuid);
3217
sdp_set_browse_groups(&record, root);
3219
sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid);
3220
svclass = sdp_list_append(NULL, &svclass_uuid);
3221
sdp_set_service_classes(&record, svclass);
3223
sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version);
3225
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3226
printf("Service Record registration failed\n");
3227
sdp_data_free(version);
3231
printf("Nokia ID service record registered\n");
3236
static unsigned char pcsuite_uuid[] = { 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00,
3237
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3239
static int add_pcsuite(sdp_session_t *session, svc_info_t *si)
3241
sdp_record_t record;
3242
sdp_list_t *root, *svclass, *proto;
3243
uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
3244
uint8_t channel = si->channel ? si->channel: 14;
3246
memset(&record, 0, sizeof(record));
3247
record.handle = si->handle;
3249
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3250
root = sdp_list_append(NULL, &root_uuid);
3251
sdp_set_browse_groups(&record, root);
3253
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3254
proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3256
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3257
proto = sdp_list_append(proto, sdp_list_append(
3258
sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3260
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3262
sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid);
3263
svclass = sdp_list_append(NULL, &svclass_uuid);
3264
sdp_set_service_classes(&record, svclass);
3266
sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL);
3268
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3269
printf("Service Record registration failed\n");
3273
printf("Nokia PC Suite service registered\n");
3278
static unsigned char nftp_uuid[] = { 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00,
3279
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3281
static unsigned char nsyncml_uuid[] = { 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x10, 0x00,
3282
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3284
static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00,
3285
0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3287
static unsigned char apple_uuid[] = { 0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90,
3288
0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 };
3290
static int add_apple(sdp_session_t *session, svc_info_t *si)
3292
sdp_record_t record;
3295
uint32_t attr783 = 0x00000000;
3296
uint32_t attr785 = 0x00000002;
3297
uint16_t attr786 = 0x1234;
3299
memset(&record, 0, sizeof(record));
3300
record.handle = si->handle;
3302
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3303
root = sdp_list_append(NULL, &root_uuid);
3304
sdp_set_browse_groups(&record, root);
3306
sdp_attr_add_new(&record, 0x0780, SDP_UUID128, (void *) apple_uuid);
3307
sdp_attr_add_new(&record, 0x0781, SDP_TEXT_STR8, (void *) "Macmini");
3308
sdp_attr_add_new(&record, 0x0782, SDP_TEXT_STR8, (void *) "PowerMac10,1");
3309
sdp_attr_add_new(&record, 0x0783, SDP_UINT32, (void *) &attr783);
3310
sdp_attr_add_new(&record, 0x0784, SDP_TEXT_STR8, (void *) "1.6.6f22");
3311
sdp_attr_add_new(&record, 0x0785, SDP_UINT32, (void *) &attr785);
3312
sdp_attr_add_new(&record, 0x0786, SDP_UUID16, (void *) &attr786);
3314
sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL);
3316
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3317
printf("Service Record registration failed\n");
3321
printf("Apple attribute service registered\n");
3326
static int add_isync(sdp_session_t *session, svc_info_t *si)
3328
sdp_record_t record;
3329
sdp_list_t *root, *svclass, *proto;
3330
uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid;
3331
uint8_t channel = si->channel ? si->channel : 16;
3333
memset(&record, 0, sizeof(record));
3334
record.handle = si->handle;
3336
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3337
root = sdp_list_append(NULL, &root_uuid);
3338
sdp_set_browse_groups(&record, root);
3340
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3341
proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3343
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3344
proto = sdp_list_append(proto, sdp_list_append(
3345
sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3347
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3349
sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID);
3350
svclass = sdp_list_append(NULL, &serial_uuid);
3352
sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID);
3353
svclass = sdp_list_append(svclass, &svclass_uuid);
3355
sdp_set_service_classes(&record, svclass);
3357
sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd.");
3359
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3360
printf("Service Record registration failed\n");
3364
printf("Apple iSync service registered\n");
3369
static int add_semchla(sdp_session_t *session, svc_info_t *si)
3371
sdp_record_t record;
3372
sdp_profile_desc_t profile;
3373
sdp_list_t *root, *svclass, *proto, *profiles;
3374
uuid_t root_uuid, service_uuid, l2cap_uuid, semchla_uuid;
3375
uint16_t psm = 0xf0f9;
3377
memset(&record, 0, sizeof(record));
3378
record.handle = si->handle;
3380
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3381
root = sdp_list_append(NULL, &root_uuid);
3382
sdp_set_browse_groups(&record, root);
3384
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3385
proto = sdp_list_append(NULL, sdp_list_append(
3386
sdp_list_append(NULL, &l2cap_uuid), sdp_data_alloc(SDP_UINT16, &psm)));
3388
sdp_uuid32_create(&semchla_uuid, 0x8e770300);
3389
proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid));
3391
sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3393
sdp_uuid32_create(&service_uuid, 0x8e771301);
3394
svclass = sdp_list_append(NULL, &service_uuid);
3396
sdp_set_service_classes(&record, svclass);
3398
sdp_uuid32_create(&profile.uuid, 0x8e771302); // Headset
3399
//sdp_uuid32_create(&profile.uuid, 0x8e771303); // Phone
3400
profile.version = 0x0100;
3401
profiles = sdp_list_append(NULL, &profile);
3402
sdp_set_profile_descs(&record, profiles);
3404
sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL);
3406
if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3407
printf("Service Record registration failed\n");
3411
/* SEMC High Level Authentication */
3412
printf("SEMC HLA service registered\n");
3417
static int add_gatt(sdp_session_t *session, svc_info_t *si)
3419
sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
3420
uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap;
3421
sdp_profile_desc_t profile;
3422
sdp_record_t record;
3423
sdp_data_t *psm, *sh, *eh;
3424
uint16_t att_psm = 27, start = 0x0001, end = 0x000f;
3427
memset(&record, 0, sizeof(sdp_record_t));
3428
record.handle = si->handle;
3429
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3430
root = sdp_list_append(NULL, &root_uuid);
3431
sdp_set_browse_groups(&record, root);
3432
sdp_list_free(root, NULL);
3434
sdp_uuid16_create(&gatt_uuid, GENERIC_ATTRIB_SVCLASS_ID);
3435
svclass_id = sdp_list_append(NULL, &gatt_uuid);
3436
sdp_set_service_classes(&record, svclass_id);
3437
sdp_list_free(svclass_id, NULL);
3439
sdp_uuid16_create(&profile.uuid, GENERIC_ATTRIB_PROFILE_ID);
3440
profile.version = 0x0100;
3441
profiles = sdp_list_append(NULL, &profile);
3442
sdp_set_profile_descs(&record, profiles);
3443
sdp_list_free(profiles, NULL);
3445
sdp_uuid16_create(&l2cap, L2CAP_UUID);
3446
proto[0] = sdp_list_append(NULL, &l2cap);
3447
psm = sdp_data_alloc(SDP_UINT16, &att_psm);
3448
proto[0] = sdp_list_append(proto[0], psm);
3449
apseq = sdp_list_append(NULL, proto[0]);
3451
sdp_uuid16_create(&proto_uuid, ATT_UUID);
3452
proto[1] = sdp_list_append(NULL, &proto_uuid);
3453
sh = sdp_data_alloc(SDP_UINT16, &start);
3454
proto[1] = sdp_list_append(proto[1], sh);
3455
eh = sdp_data_alloc(SDP_UINT16, &end);
3456
proto[1] = sdp_list_append(proto[1], eh);
3457
apseq = sdp_list_append(apseq, proto[1]);
3459
aproto = sdp_list_append(NULL, apseq);
3460
sdp_set_access_protos(&record, aproto);
3462
sdp_set_info_attr(&record, "Generic Attribute Profile", "BlueZ", NULL);
3464
sdp_set_url_attr(&record, "http://www.bluez.org/",
3465
"http://www.bluez.org/", "http://www.bluez.org/");
3467
sdp_set_service_id(&record, gatt_uuid);
3469
ret = sdp_device_record_register(session, &interface, &record,
3470
SDP_RECORD_PERSIST);
3472
printf("Service Record registration failed\n");
3474
printf("Generic Attribute Profile Service registered\n");
3479
sdp_list_free(proto[0], NULL);
3480
sdp_list_free(proto[1], NULL);
3481
sdp_list_free(apseq, NULL);
3482
sdp_list_free(aproto, NULL);
3490
int (*add)(sdp_session_t *sess, svc_info_t *si);
3491
unsigned char *uuid;
3493
{ "DID", PNP_INFO_SVCLASS_ID, NULL, },
3495
{ "SP", SERIAL_PORT_SVCLASS_ID, add_sp },
3496
{ "DUN", DIALUP_NET_SVCLASS_ID, add_dun },
3497
{ "LAN", LAN_ACCESS_SVCLASS_ID, add_lan },
3498
{ "FAX", FAX_SVCLASS_ID, add_fax },
3499
{ "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush },
3500
{ "FTP", OBEX_FILETRANS_SVCLASS_ID, add_ftp },
3501
{ "PRINT", DIRECT_PRINTING_SVCLASS_ID, add_directprint },
3503
{ "HS", HEADSET_SVCLASS_ID, add_headset },
3504
{ "HSAG", HEADSET_AGW_SVCLASS_ID, add_headset_ag },
3505
{ "HF", HANDSFREE_SVCLASS_ID, add_handsfree },
3506
{ "HFAG", HANDSFREE_AGW_SVCLASS_ID, add_handsfree_ag},
3507
{ "SAP", SAP_SVCLASS_ID, add_simaccess },
3508
{ "PBAP", PBAP_SVCLASS_ID, add_pbap, },
3510
{ "NAP", NAP_SVCLASS_ID, add_nap },
3511
{ "GN", GN_SVCLASS_ID, add_gn },
3512
{ "PANU", PANU_SVCLASS_ID, add_panu },
3514
{ "HCRP", HCR_SVCLASS_ID, NULL },
3515
{ "HID", HID_SVCLASS_ID, NULL },
3516
{ "KEYB", HID_SVCLASS_ID, add_hid_keyb },
3517
{ "WIIMOTE", HID_SVCLASS_ID, add_hid_wiimote },
3518
{ "CIP", CIP_SVCLASS_ID, add_cip },
3519
{ "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp },
3521
{ "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source },
3522
{ "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink },
3523
{ "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct },
3524
{ "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg },
3526
{ "UDIUE", UDI_MT_SVCLASS_ID, add_udi_ue },
3527
{ "UDITE", UDI_TA_SVCLASS_ID, add_udi_te },
3529
{ "SEMCHLA", 0x8e771301, add_semchla },
3531
{ "SR1", 0, add_sr1, sr1_uuid },
3532
{ "SYNCML", 0, add_syncml, syncmlc_uuid },
3533
{ "SYNCMLSERV", 0, NULL, syncmls_uuid },
3534
{ "ACTIVESYNC", 0, add_activesync, async_uuid },
3535
{ "HOTSYNC", 0, add_hotsync, hotsync_uuid },
3536
{ "PALMOS", 0, add_palmos, palmos_uuid },
3537
{ "NOKID", 0, add_nokiaid, nokid_uuid },
3538
{ "PCSUITE", 0, add_pcsuite, pcsuite_uuid },
3539
{ "NFTP", 0, NULL, nftp_uuid },
3540
{ "NSYNCML", 0, NULL, nsyncml_uuid },
3541
{ "NGAGE", 0, NULL, ngage_uuid },
3542
{ "APPLE", 0, add_apple, apple_uuid },
3544
{ "ISYNC", APPLE_AGENT_SVCLASS_ID, add_isync, },
3545
{ "GATT", GENERIC_ATTRIB_SVCLASS_ID, add_gatt, },
3550
/* Add local service */
3551
static int add_service(bdaddr_t *bdaddr, svc_info_t *si)
3553
sdp_session_t *sess;
3559
sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
3563
for (i = 0; service[i].name; i++)
3564
if (!strcasecmp(service[i].name, si->name)) {
3566
ret = service[i].add(sess, si);
3570
printf("Unknown service name: %s\n", si->name);
3579
static struct option add_options[] = {
3580
{ "help", 0, 0, 'h' },
3581
{ "handle", 1, 0, 'r' },
3582
{ "psm", 1, 0, 'p' },
3583
{ "channel", 1, 0, 'c' },
3584
{ "network", 1, 0, 'n' },
3588
static const char *add_help =
3590
"\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n";
3592
static int cmd_add(int argc, char **argv)
3597
memset(&si, 0, sizeof(si));
3598
si.handle = 0xffffffff;
3600
for_each_opt(opt, add_options, 0) {
3603
if (strncasecmp(optarg, "0x", 2))
3604
si.handle = atoi(optarg);
3606
si.handle = strtol(optarg + 2, NULL, 16);
3609
if (strncasecmp(optarg, "0x", 2))
3610
si.psm = atoi(optarg);
3612
si.psm = strtol(optarg + 2, NULL, 16);
3615
if (strncasecmp(optarg, "0x", 2))
3616
si.channel = atoi(optarg);
3618
si.channel = strtol(optarg + 2, NULL, 16);
3621
if (strncasecmp(optarg, "0x", 2))
3622
si.network = atoi(optarg);
3624
si.network = strtol(optarg + 2, NULL, 16);
3627
printf("%s", add_help);
3636
printf("%s", add_help);
3640
si.name = strdup(argv[0]);
3642
return add_service(0, &si);
3645
/* Delete local service */
3646
static int del_service(bdaddr_t *bdaddr, void *arg)
3648
uint32_t handle, range = 0x0000ffff;
3650
sdp_session_t *sess;
3654
printf("Record handle was not specified.\n");
3658
sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
3660
printf("No local SDP server!\n");
3664
handle = strtoul((char *)arg, 0, 16);
3665
attr = sdp_list_append(0, &range);
3666
rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
3667
sdp_list_free(attr, 0);
3670
printf("Service Record not found.\n");
3675
if (sdp_device_record_unregister(sess, &interface, rec)) {
3676
printf("Failed to unregister service record: %s\n", strerror(errno));
3681
printf("Service Record deleted.\n");
3687
static struct option del_options[] = {
3688
{ "help", 0, 0, 'h' },
3692
static const char *del_help =
3694
"\tdel record_handle\n";
3696
static int cmd_del(int argc, char **argv)
3700
for_each_opt(opt, del_options, 0) {
3703
printf("%s", del_help);
3712
printf("%s", del_help);
3716
return del_service(NULL, argv[0]);
3720
* Perform an inquiry and search/browse all peer found.
3722
static void inquiry(handler_t handler, void *arg)
3724
inquiry_info ii[20];
3728
printf("Inquiring ...\n");
3729
if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
3730
printf("Inquiry failed\n");
3734
for (i = 0; i < count; i++)
3735
handler(&ii[i].bdaddr, arg);
3738
static void doprintf(void *data, const char *str)
3744
* Search for a specific SDP service
3746
static int do_search(bdaddr_t *bdaddr, struct search_context *context)
3748
sdp_list_t *attrid, *search, *seq, *next;
3749
uint32_t range = 0x0000ffff;
3751
sdp_session_t *sess;
3754
inquiry(do_search, context);
3758
sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
3759
ba2str(bdaddr, str);
3761
printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
3765
if (context->view != RAW_VIEW) {
3767
printf("Searching for %s on %s ...\n", context->svc, str);
3769
printf("Browsing %s ...\n", str);
3772
attrid = sdp_list_append(0, &range);
3773
search = sdp_list_append(0, &context->group);
3774
if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) {
3775
printf("Service Search failed: %s\n", strerror(errno));
3779
sdp_list_free(attrid, 0);
3780
sdp_list_free(search, 0);
3782
for (; seq; seq = next) {
3783
sdp_record_t *rec = (sdp_record_t *) seq->data;
3784
struct search_context sub_context;
3786
switch (context->view) {
3788
/* Display user friendly form */
3789
print_service_attr(rec);
3793
/* Display full tree */
3794
print_tree_attr(rec);
3798
/* Display raw XML tree */
3799
convert_sdp_record_to_xml(rec, 0, doprintf);
3802
/* Display raw tree */
3803
print_raw_attr(rec);
3807
if (sdp_get_group_id(rec, &sub_context.group) != -1) {
3808
/* Set the subcontext for browsing the sub tree */
3809
memcpy(&sub_context, context, sizeof(struct search_context));
3810
/* Browse the next level down if not done */
3811
if (sub_context.group.value.uuid16 != context->group.value.uuid16)
3812
do_search(bdaddr, &sub_context);
3816
sdp_record_free(rec);
3823
static struct option browse_options[] = {
3824
{ "help", 0, 0, 'h' },
3825
{ "tree", 0, 0, 't' },
3826
{ "raw", 0, 0, 'r' },
3827
{ "xml", 0, 0, 'x' },
3828
{ "uuid", 1, 0, 'u' },
3829
{ "l2cap", 0, 0, 'l' },
3833
static const char *browse_help =
3835
"\tbrowse [--tree] [--raw] [--xml] [--uuid uuid] [--l2cap] [bdaddr]\n";
3838
* Browse the full SDP database (i.e. list all services starting from the
3841
static int cmd_browse(int argc, char **argv)
3843
struct search_context context;
3846
/* Initialise context */
3847
memset(&context, '\0', sizeof(struct search_context));
3848
/* We want to browse the top-level/root */
3849
sdp_uuid16_create(&context.group, PUBLIC_BROWSE_GROUP);
3851
for_each_opt(opt, browse_options, 0) {
3854
context.view = TREE_VIEW;
3857
context.view = RAW_VIEW;
3860
context.view = XML_VIEW;
3863
if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) {
3864
printf("Invalid uuid %s\n", optarg);
3867
sdp_uuid16_create(&context.group, num);
3870
sdp_uuid16_create(&context.group, L2CAP_UUID);
3873
printf("%s", browse_help);
3883
estr2ba(argv[0], &bdaddr);
3884
return do_search(&bdaddr, &context);
3887
return do_search(NULL, &context);
3890
static struct option search_options[] = {
3891
{ "help", 0, 0, 'h' },
3892
{ "bdaddr", 1, 0, 'b' },
3893
{ "tree", 0, 0, 't' },
3894
{ "raw", 0, 0, 'r' },
3895
{ "xml", 0, 0, 'x' },
3899
static const char *search_help =
3901
"\tsearch [--bdaddr bdaddr] [--tree] [--raw] [--xml] SERVICE\n"
3902
"SERVICE is a name (string) or UUID (0x1002)\n";
3905
* Search for a specific SDP service
3907
* Note : we should support multiple services on the command line :
3908
* sdptool search 0x0100 0x000f 0x1002
3909
* (this would search a service supporting both L2CAP and BNEP directly in
3910
* the top level browse group)
3912
static int cmd_search(int argc, char **argv)
3914
struct search_context context;
3915
unsigned char *uuid = NULL;
3922
/* Initialise context */
3923
memset(&context, '\0', sizeof(struct search_context));
3925
for_each_opt(opt, search_options, 0) {
3928
estr2ba(optarg, &bdaddr);
3932
context.view = TREE_VIEW;
3935
context.view = RAW_VIEW;
3938
context.view = XML_VIEW;
3941
printf("%s", search_help);
3950
printf("%s", search_help);
3954
/* Note : we need to find a way to support search combining
3955
* multiple services */
3956
context.svc = strdup(argv[0]);
3957
if (!strncasecmp(context.svc, "0x", 2)) {
3959
/* This is a UUID16, just convert to int */
3960
sscanf(context.svc + 2, "%X", &num);
3962
printf("Class 0x%X\n", class);
3964
/* Convert class name to an UUID */
3966
for (i = 0; service[i].name; i++)
3967
if (strcasecmp(context.svc, service[i].name) == 0) {
3968
class = service[i].class;
3969
uuid = service[i].uuid;
3972
if (!class && !uuid) {
3973
printf("Unknown service %s\n", context.svc);
3979
if (class & 0xffff0000)
3980
sdp_uuid32_create(&context.group, class);
3982
uint16_t class16 = class & 0xffff;
3983
sdp_uuid16_create(&context.group, class16);
3986
sdp_uuid128_create(&context.group, uuid);
3989
return do_search(&bdaddr, &context);
3991
return do_search(NULL, &context);
3995
* Show how to get a specific SDP record by its handle.
3996
* Not really useful to the user, just show how it can be done...
3998
static int get_service(bdaddr_t *bdaddr, struct search_context *context, int quite)
4001
uint32_t range = 0x0000ffff;
4003
sdp_session_t *session = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
4007
ba2str(bdaddr, str);
4008
printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
4012
attrid = sdp_list_append(0, &range);
4013
rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid);
4014
sdp_list_free(attrid, 0);
4019
printf("Service get request failed.\n");
4025
switch (context->view) {
4027
/* Display user friendly form */
4028
print_service_attr(rec);
4032
/* Display full tree */
4033
print_tree_attr(rec);
4037
/* Display raw XML tree */
4038
convert_sdp_record_to_xml(rec, 0, doprintf);
4041
/* Display raw tree */
4042
print_raw_attr(rec);
4046
sdp_record_free(rec);
4050
static struct option records_options[] = {
4051
{ "help", 0, 0, 'h' },
4052
{ "tree", 0, 0, 't' },
4053
{ "raw", 0, 0, 'r' },
4054
{ "xml", 0, 0, 'x' },
4058
static const char *records_help =
4060
"\trecords [--tree] [--raw] [--xml] bdaddr\n";
4063
* Request possible SDP service records
4065
static int cmd_records(int argc, char **argv)
4067
struct search_context context;
4068
uint32_t base[] = { 0x10000, 0x10300, 0x10500,
4069
0x1002e, 0x110b, 0x90000, 0x2008000,
4070
0x4000000, 0x100000, 0x1000000,
4071
0x4f491100, 0x4f491200 };
4073
unsigned int i, n, num = 32;
4076
/* Initialise context */
4077
memset(&context, '\0', sizeof(struct search_context));
4079
for_each_opt(opt, records_options, 0) {
4082
context.view = TREE_VIEW;
4085
context.view = RAW_VIEW;
4088
context.view = XML_VIEW;
4091
printf("%s", records_help);
4100
printf("%s", records_help);
4104
/* Convert command line parameters */
4105
estr2ba(argv[0], &bdaddr);
4107
for (i = 0; i < sizeof(base) / sizeof(uint32_t); i++)
4108
for (n = 0; n < num; n++) {
4109
context.handle = base[i] + n;
4110
err = get_service(&bdaddr, &context, 1);
4118
static struct option get_options[] = {
4119
{ "help", 0, 0, 'h' },
4120
{ "bdaddr", 1, 0, 'b' },
4121
{ "tree", 0, 0, 't' },
4122
{ "raw", 0, 0, 'r' },
4123
{ "xml", 0, 0, 'x' },
4127
static const char *get_help =
4129
"\tget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\n";
4132
* Get a specific SDP record on the local SDP server
4134
static int cmd_get(int argc, char **argv)
4136
struct search_context context;
4141
/* Initialise context */
4142
memset(&context, '\0', sizeof(struct search_context));
4144
for_each_opt(opt, get_options, 0) {
4147
estr2ba(optarg, &bdaddr);
4151
context.view = TREE_VIEW;
4154
context.view = RAW_VIEW;
4157
context.view = XML_VIEW;
4160
printf("%s", get_help);
4169
printf("%s", get_help);
4173
/* Convert command line parameters */
4174
context.handle = strtoul(argv[0], 0, 16);
4176
return get_service(has_addr ? &bdaddr : BDADDR_LOCAL, &context, 0);
4181
int (*func)(int argc, char **argv);
4184
{ "search", cmd_search, "Search for a service" },
4185
{ "browse", cmd_browse, "Browse all available services" },
4186
{ "records", cmd_records, "Request all records" },
4187
{ "add", cmd_add, "Add local service" },
4188
{ "del", cmd_del, "Delete local service" },
4189
{ "get", cmd_get, "Get local service" },
4190
{ "setattr", cmd_setattr, "Set/Add attribute to a SDP record" },
4191
{ "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" },
4195
static void usage(void)
4199
printf("sdptool - SDP tool v%s\n", VERSION);
4201
"\tsdptool [options] <command> [command parameters]\n");
4203
"\t-h\t\tDisplay help\n"
4204
"\t-i\t\tSpecify source interface\n");
4206
printf("Commands:\n");
4207
for (i = 0; command[i].cmd; i++)
4208
printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc);
4210
printf("\nServices:\n\t");
4211
for (i = 0; service[i].name; i++) {
4212
printf("%s ", service[i].name);
4213
pos += strlen(service[i].name) + 1;
4222
static struct option main_options[] = {
4223
{ "help", 0, 0, 'h' },
4224
{ "device", 1, 0, 'i' },
4228
int main(int argc, char *argv[])
4232
bacpy(&interface, BDADDR_ANY);
4234
while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
4237
if (!strncmp(optarg, "hci", 3))
4238
hci_devba(atoi(optarg + 3), &interface);
4240
str2ba(optarg, &interface);
4261
for (i = 0; command[i].cmd; i++)
4262
if (strncmp(command[i].cmd, argv[0], 4) == 0)
4263
return command[i].func(argc, argv);