~bluetooth/bluez/vivid-phone-overlay

« back to all changes in this revision

Viewing changes to tools/sdptool.c

  • Committer: Simon Fels
  • Date: 2015-09-11 09:01:46 UTC
  • Revision ID: morphis@gravedo.de-20150911090146-4c0ln9s7ec3xf0nx
Import package bluez_4.101-0ubuntu25.1~overlay4 from stable phone overlay PPA

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  BlueZ - Bluetooth protocol stack for Linux
 
4
 *
 
5
 *  Copyright (C) 2001-2002  Nokia Corporation
 
6
 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@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>
 
10
 *
 
11
 *
 
12
 *  This program is free software; you can redistribute it and/or modify
 
13
 *  it under the terms of the GNU General Public License as published by
 
14
 *  the Free Software Foundation; either version 2 of the License, or
 
15
 *  (at your option) any later version.
 
16
 *
 
17
 *  This program is distributed in the hope that it will be useful,
 
18
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 *  GNU General Public License for more details.
 
21
 *
 
22
 *  You should have received a copy of the GNU General Public License
 
23
 *  along with this program; if not, write to the Free Software
 
24
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
25
 *
 
26
 */
 
27
 
 
28
#ifdef HAVE_CONFIG_H
 
29
#include <config.h>
 
30
#endif
 
31
 
 
32
#include <stdio.h>
 
33
#include <errno.h>
 
34
#include <ctype.h>
 
35
#include <stdlib.h>
 
36
#include <string.h>
 
37
#include <getopt.h>
 
38
#include <sys/socket.h>
 
39
 
 
40
#include <bluetooth/bluetooth.h>
 
41
#include <bluetooth/hci.h>
 
42
#include <bluetooth/hci_lib.h>
 
43
#include <bluetooth/sdp.h>
 
44
#include <bluetooth/sdp_lib.h>
 
45
 
 
46
#include <netinet/in.h>
 
47
 
 
48
#include "sdp-xml.h"
 
49
 
 
50
#ifndef APPLE_AGENT_SVCLASS_ID
 
51
#define APPLE_AGENT_SVCLASS_ID 0x2112
 
52
#endif
 
53
 
 
54
#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1)
 
55
 
 
56
/*
 
57
 * Convert a string to a BDADDR, with a few "enhancements" - Jean II
 
58
 */
 
59
static int estr2ba(char *str, bdaddr_t *ba)
 
60
{
 
61
        /* Only trap "local", "any" is already dealt with */
 
62
        if(!strcmp(str, "local")) {
 
63
                bacpy(ba, BDADDR_LOCAL);
 
64
                return 0;
 
65
        }
 
66
        return str2ba(str, ba);
 
67
}
 
68
 
 
69
#define DEFAULT_VIEW    0       /* Display only known attribute */
 
70
#define TREE_VIEW       1       /* Display full attribute tree */
 
71
#define RAW_VIEW        2       /* Display raw tree */
 
72
#define XML_VIEW        3       /* Display xml tree */
 
73
 
 
74
/* Pass args to the inquiry/search handler */
 
75
struct search_context {
 
76
        char            *svc;           /* Service */
 
77
        uuid_t          group;          /* Browse group */
 
78
        int             view;           /* View mode */
 
79
        uint32_t        handle;         /* Service record handle */
 
80
};
 
81
 
 
82
typedef int (*handler_t)(bdaddr_t *bdaddr, struct search_context *arg);
 
83
 
 
84
static char UUID_str[MAX_LEN_UUID_STR];
 
85
static bdaddr_t interface;
 
86
 
 
87
/* Definition of attribute members */
 
88
struct member_def {
 
89
        char *name;
 
90
};
 
91
 
 
92
/* Definition of an attribute */
 
93
struct attrib_def {
 
94
        int                     num;            /* Numeric ID - 16 bits */
 
95
        char                    *name;          /* User readable name */
 
96
        struct member_def       *members;       /* Definition of attribute args */
 
97
        int                     member_max;     /* Max of attribute arg definitions */
 
98
};
 
99
 
 
100
/* Definition of a service or protocol */
 
101
struct uuid_def {
 
102
        int                     num;            /* Numeric ID - 16 bits */
 
103
        char                    *name;          /* User readable name */
 
104
        struct attrib_def       *attribs;       /* Specific attribute definitions */
 
105
        int                     attrib_max;     /* Max of attribute definitions */
 
106
};
 
107
 
 
108
/* Context information about current attribute */
 
109
struct attrib_context {
 
110
        struct uuid_def         *service;       /* Service UUID, if known */
 
111
        struct attrib_def       *attrib;        /* Description of the attribute */
 
112
        int                     member_index;   /* Index of current attribute member */
 
113
};
 
114
 
 
115
/* Context information about the whole service */
 
116
struct service_context {
 
117
        struct uuid_def         *service;       /* Service UUID, if known */
 
118
};
 
119
 
 
120
/* Allow us to do nice formatting of the lists */
 
121
static char *indent_spaces = "                                         ";
 
122
 
 
123
/* ID of the service attribute.
 
124
 * Most attributes after 0x200 are defined based on the service, so
 
125
 * we need to find what is the service (which is messy) - Jean II */
 
126
#define SERVICE_ATTR    0x1
 
127
 
 
128
/* Definition of the optional arguments in protocol list */
 
129
static struct member_def protocol_members[] = {
 
130
        { "Protocol"            },
 
131
        { "Channel/Port"        },
 
132
        { "Version"             },
 
133
};
 
134
 
 
135
/* Definition of the optional arguments in profile list */
 
136
static struct member_def profile_members[] = {
 
137
        { "Profile"     },
 
138
        { "Version"     },
 
139
};
 
140
 
 
141
/* Definition of the optional arguments in Language list */
 
142
static struct member_def language_members[] = {
 
143
        { "Code ISO639"         },
 
144
        { "Encoding"            },
 
145
        { "Base Offset"         },
 
146
};
 
147
 
 
148
/* Name of the various common attributes. See BT assigned numbers */
 
149
static struct attrib_def attrib_names[] = {
 
150
        { 0x0, "ServiceRecordHandle", NULL, 0 },
 
151
        { 0x1, "ServiceClassIDList", NULL, 0 },
 
152
        { 0x2, "ServiceRecordState", NULL, 0 },
 
153
        { 0x3, "ServiceID", NULL, 0 },
 
154
        { 0x4, "ProtocolDescriptorList",
 
155
                protocol_members, sizeof(protocol_members)/sizeof(struct member_def) },
 
156
        { 0x5, "BrowseGroupList", NULL, 0 },
 
157
        { 0x6, "LanguageBaseAttributeIDList",
 
158
                language_members, sizeof(language_members)/sizeof(struct member_def) },
 
159
        { 0x7, "ServiceInfoTimeToLive", NULL, 0 },
 
160
        { 0x8, "ServiceAvailability", NULL, 0 },
 
161
        { 0x9, "BluetoothProfileDescriptorList",
 
162
                profile_members, sizeof(profile_members)/sizeof(struct member_def) },
 
163
        { 0xA, "DocumentationURL", NULL, 0 },
 
164
        { 0xB, "ClientExecutableURL", NULL, 0 },
 
165
        { 0xC, "IconURL", NULL, 0 },
 
166
        { 0xD, "AdditionalProtocolDescriptorLists", NULL, 0 },
 
167
        /* Definitions after that are tricky (per profile or offset) */
 
168
};
 
169
 
 
170
const int attrib_max = sizeof(attrib_names)/sizeof(struct attrib_def);
 
171
 
 
172
/* Name of the various SPD attributes. See BT assigned numbers */
 
173
static struct attrib_def sdp_attrib_names[] = {
 
174
        { 0x200, "VersionNumberList", NULL, 0 },
 
175
        { 0x201, "ServiceDatabaseState", NULL, 0 },
 
176
};
 
177
 
 
178
/* Name of the various SPD attributes. See BT assigned numbers */
 
179
static struct attrib_def browse_attrib_names[] = {
 
180
        { 0x200, "GroupID", NULL, 0 },
 
181
};
 
182
 
 
183
/* Name of the various Device ID attributes. See Device Id spec. */
 
184
static struct attrib_def did_attrib_names[] = {
 
185
        { 0x200, "SpecificationID", NULL, 0 },
 
186
        { 0x201, "VendorID", NULL, 0 },
 
187
        { 0x202, "ProductID", NULL, 0 },
 
188
        { 0x203, "Version", NULL, 0 },
 
189
        { 0x204, "PrimaryRecord", NULL, 0 },
 
190
        { 0x205, "VendorIDSource", NULL, 0 },
 
191
};
 
192
 
 
193
/* Name of the various HID attributes. See HID spec. */
 
194
static struct attrib_def hid_attrib_names[] = {
 
195
        { 0x200, "DeviceReleaseNum", NULL, 0 },
 
196
        { 0x201, "ParserVersion", NULL, 0 },
 
197
        { 0x202, "DeviceSubclass", NULL, 0 },
 
198
        { 0x203, "CountryCode", NULL, 0 },
 
199
        { 0x204, "VirtualCable", NULL, 0 },
 
200
        { 0x205, "ReconnectInitiate", NULL, 0 },
 
201
        { 0x206, "DescriptorList", NULL, 0 },
 
202
        { 0x207, "LangIDBaseList", NULL, 0 },
 
203
        { 0x208, "SDPDisable", NULL, 0 },
 
204
        { 0x209, "BatteryPower", NULL, 0 },
 
205
        { 0x20a, "RemoteWakeup", NULL, 0 },
 
206
        { 0x20b, "ProfileVersion", NULL, 0 },
 
207
        { 0x20c, "SupervisionTimeout", NULL, 0 },
 
208
        { 0x20d, "NormallyConnectable", NULL, 0 },
 
209
        { 0x20e, "BootDevice", NULL, 0 },
 
210
};
 
211
 
 
212
/* Name of the various PAN attributes. See BT assigned numbers */
 
213
/* Note : those need to be double checked - Jean II */
 
214
static struct attrib_def pan_attrib_names[] = {
 
215
        { 0x200, "IpSubnet", NULL, 0 },         /* Obsolete ??? */
 
216
        { 0x30A, "SecurityDescription", NULL, 0 },
 
217
        { 0x30B, "NetAccessType", NULL, 0 },
 
218
        { 0x30C, "MaxNetAccessrate", NULL, 0 },
 
219
        { 0x30D, "IPv4Subnet", NULL, 0 },
 
220
        { 0x30E, "IPv6Subnet", NULL, 0 },
 
221
};
 
222
 
 
223
/* Name of the various Generic-Audio attributes. See BT assigned numbers */
 
224
/* Note : totally untested - Jean II */
 
225
static struct attrib_def audio_attrib_names[] = {
 
226
        { 0x302, "Remote audio volume control", NULL, 0 },
 
227
};
 
228
 
 
229
/* Name of the various GOEP attributes. See BT assigned numbers */
 
230
static struct attrib_def goep_attrib_names[] = {
 
231
        { 0x200, "GoepL2capPsm", NULL, 0 },
 
232
};
 
233
 
 
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 },
 
259
        /* -- Services -- */
 
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 },
 
274
        { 0x1108, "Headset",
 
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 },
 
320
        /* ... */
 
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 },
 
328
        /* ... */
 
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 },
 
336
};
 
337
 
 
338
static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def);
 
339
 
 
340
static void sdp_data_printf(sdp_data_t *, struct attrib_context *, int);
 
341
 
 
342
/*
 
343
 * Parse a UUID.
 
344
 * The BT assigned numbers only list UUID16, so I'm not sure the
 
345
 * other types will ever get used...
 
346
 */
 
347
static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent)
 
348
{
 
349
        if (uuid) {
 
350
                if (uuid->type == SDP_UUID16) {
 
351
                        uint16_t uuidNum = uuid->value.uuid16;
 
352
                        struct uuid_def *uuidDef = NULL;
 
353
                        int i;
 
354
 
 
355
                        for (i = 0; i < uuid16_max; i++)
 
356
                                if (uuid16_names[i].num == uuidNum) {
 
357
                                        uuidDef = &uuid16_names[i];
 
358
                                        break;
 
359
                                }
 
360
 
 
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;
 
365
                        }
 
366
 
 
367
                        if (uuidDef)
 
368
                                printf("%.*sUUID16 : 0x%.4x - %s\n",
 
369
                                        indent, indent_spaces, uuidNum, uuidDef->name);
 
370
                        else
 
371
                                printf("%.*sUUID16 : 0x%.4x\n",
 
372
                                        indent, indent_spaces, uuidNum);
 
373
                } else if (uuid->type == SDP_UUID32) {
 
374
                        struct uuid_def *uuidDef = NULL;
 
375
                        int i;
 
376
 
 
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];
 
382
                                                break;
 
383
                                        }
 
384
                        }
 
385
 
 
386
                        if (uuidDef)
 
387
                                printf("%.*sUUID32 : 0x%.8x - %s\n",
 
388
                                        indent, indent_spaces, uuid->value.uuid32, uuidDef->name);
 
389
                        else
 
390
                                printf("%.*sUUID32 : 0x%.8x\n",
 
391
                                        indent, indent_spaces, uuid->value.uuid32);
 
392
                } else if (uuid->type == SDP_UUID128) {
 
393
                        unsigned int data0;
 
394
                        unsigned short data1;
 
395
                        unsigned short data2;
 
396
                        unsigned short data3;
 
397
                        unsigned int data4;
 
398
                        unsigned short data5;
 
399
 
 
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);
 
406
 
 
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));
 
411
                } else
 
412
                        printf("%.*sEnum type of UUID not set\n",
 
413
                                indent, indent_spaces);
 
414
        } else
 
415
                printf("%.*sNull passed to print UUID\n",
 
416
                                indent, indent_spaces);
 
417
}
 
418
 
 
419
/*
 
420
 * Parse a sequence of data elements (i.e. a list)
 
421
 */
 
422
static void printf_dataseq(sdp_data_t * pData, struct attrib_context *context, int indent)
 
423
{
 
424
        sdp_data_t *sdpdata = NULL;
 
425
 
 
426
        sdpdata = pData;
 
427
        if (sdpdata) {
 
428
                context->member_index = 0;
 
429
                do {
 
430
                        sdp_data_printf(sdpdata, context, indent + 2);
 
431
                        sdpdata = sdpdata->next;
 
432
                        context->member_index++;
 
433
                } while (sdpdata);
 
434
        } else {
 
435
                printf("%.*sBroken dataseq link\n", indent, indent_spaces);
 
436
        }
 
437
}
 
438
 
 
439
/*
 
440
 * Parse a single data element (either in the attribute or in a data
 
441
 * sequence).
 
442
 */
 
443
static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent)
 
444
{
 
445
        char *member_name = NULL;
 
446
 
 
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;
 
451
        }
 
452
 
 
453
        switch (sdpdata->dtd) {
 
454
        case SDP_DATA_NIL:
 
455
                printf("%.*sNil\n", indent, indent_spaces);
 
456
                break;
 
457
        case SDP_BOOL:
 
458
        case SDP_UINT8:
 
459
        case SDP_UINT16:
 
460
        case SDP_UINT32:
 
461
        case SDP_UINT64:
 
462
        case SDP_UINT128:
 
463
        case SDP_INT8:
 
464
        case SDP_INT16:
 
465
        case SDP_INT32:
 
466
        case SDP_INT64:
 
467
        case SDP_INT128:
 
468
                if (member_name) {
 
469
                        printf("%.*s%s (Integer) : 0x%x\n",
 
470
                                indent, indent_spaces, member_name, sdpdata->val.uint32);
 
471
                } else {
 
472
                        printf("%.*sInteger : 0x%x\n", indent, indent_spaces,
 
473
                                sdpdata->val.uint32);
 
474
                }
 
475
                break;
 
476
 
 
477
        case SDP_UUID16:
 
478
        case SDP_UUID32:
 
479
        case SDP_UUID128:
 
480
                //printf("%.*sUUID\n", indent, indent_spaces);
 
481
                sdp_uuid_printf(&sdpdata->val.uuid, context, indent);
 
482
                break;
 
483
 
 
484
        case SDP_TEXT_STR8:
 
485
        case SDP_TEXT_STR16:
 
486
        case SDP_TEXT_STR32:
 
487
                if (sdpdata->unitSize > (int) strlen(sdpdata->val.str)) {
 
488
                        int i;
 
489
                        printf("%.*sData :", indent, indent_spaces);
 
490
                        for (i = 0; i < sdpdata->unitSize; i++)
 
491
                                printf(" %02x", (unsigned char) sdpdata->val.str[i]);
 
492
                        printf("\n");
 
493
                } else
 
494
                        printf("%.*sText : \"%s\"\n", indent, indent_spaces, sdpdata->val.str);
 
495
                break;
 
496
        case SDP_URL_STR8:
 
497
        case SDP_URL_STR16:
 
498
        case SDP_URL_STR32:
 
499
                printf("%.*sURL : %s\n", indent, indent_spaces, sdpdata->val.str);
 
500
                break;
 
501
 
 
502
        case SDP_SEQ8:
 
503
        case SDP_SEQ16:
 
504
        case SDP_SEQ32:
 
505
                printf("%.*sData Sequence\n", indent, indent_spaces);
 
506
                printf_dataseq(sdpdata->val.dataseq, context, indent);
 
507
                break;
 
508
 
 
509
        case SDP_ALT8:
 
510
        case SDP_ALT16:
 
511
        case SDP_ALT32:
 
512
                printf("%.*sData Sequence Alternates\n", indent, indent_spaces);
 
513
                printf_dataseq(sdpdata->val.dataseq, context, indent);
 
514
                break;
 
515
        }
 
516
}
 
517
 
 
518
/*
 
519
 * Parse a single attribute.
 
520
 */
 
521
static void print_tree_attr_func(void *value, void *userData)
 
522
{
 
523
        sdp_data_t *sdpdata = value;
 
524
        uint16_t attrId;
 
525
        struct service_context *service = (struct service_context *) userData;
 
526
        struct attrib_context context;
 
527
        struct attrib_def *attrDef = NULL;
 
528
        int i;
 
529
 
 
530
        if (!sdpdata)
 
531
                return;
 
532
 
 
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];
 
538
                        break;
 
539
                }
 
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];
 
548
                                break;
 
549
                        }
 
550
        }
 
551
 
 
552
        if (attrDef)
 
553
                printf("Attribute Identifier : 0x%x - %s\n", attrId, attrDef->name);
 
554
        else
 
555
                printf("Attribute Identifier : 0x%x\n", attrId);
 
556
        /* Build context */
 
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);
 
562
        /* Update service */
 
563
        service->service = context.service;
 
564
}
 
565
 
 
566
/*
 
567
 * Main entry point of this library. Parse a SDP record.
 
568
 * We assume the record has already been read, parsed and cached
 
569
 * locally. Jean II
 
570
 */
 
571
static void print_tree_attr(sdp_record_t *rec)
 
572
{
 
573
        if (rec && rec->attrlist) {
 
574
                struct service_context service = { NULL };
 
575
                sdp_list_foreach(rec->attrlist, print_tree_attr_func, &service);
 
576
        }
 
577
}
 
578
 
 
579
static void print_raw_data(sdp_data_t *data, int indent)
 
580
{
 
581
        struct uuid_def *def;
 
582
        int i, hex;
 
583
 
 
584
        if (!data)
 
585
                return;
 
586
 
 
587
        for (i = 0; i < indent; i++)
 
588
                printf("\t");
 
589
 
 
590
        switch (data->dtd) {
 
591
        case SDP_DATA_NIL:
 
592
                printf("NIL\n");
 
593
                break;
 
594
        case SDP_BOOL:
 
595
                printf("Bool %s\n", data->val.uint8 ? "True" : "False");
 
596
                break;
 
597
        case SDP_UINT8:
 
598
                printf("UINT8 0x%02x\n", data->val.uint8);
 
599
                break;
 
600
        case SDP_UINT16:
 
601
                printf("UINT16 0x%04x\n", data->val.uint16);
 
602
                break;
 
603
        case SDP_UINT32:
 
604
                printf("UINT32 0x%08x\n", data->val.uint32);
 
605
                break;
 
606
        case SDP_UINT64:
 
607
                printf("UINT64 0x%016jx\n", data->val.uint64);
 
608
                break;
 
609
        case SDP_UINT128:
 
610
                printf("UINT128 ...\n");
 
611
                break;
 
612
        case SDP_INT8:
 
613
                printf("INT8 %d\n", data->val.int8);
 
614
                break;
 
615
        case SDP_INT16:
 
616
                printf("INT16 %d\n", data->val.int16);
 
617
                break;
 
618
        case SDP_INT32:
 
619
                printf("INT32 %d\n", data->val.int32);
 
620
                break;
 
621
        case SDP_INT64:
 
622
                printf("INT64 %jd\n", data->val.int64);
 
623
                break;
 
624
        case SDP_INT128:
 
625
                printf("INT128 ...\n");
 
626
                break;
 
627
        case SDP_UUID16:
 
628
        case SDP_UUID32:
 
629
        case SDP_UUID128:
 
630
                switch (data->val.uuid.type) {
 
631
                case SDP_UUID16:
 
632
                        def = NULL;
 
633
                        for (i = 0; i < uuid16_max; i++)
 
634
                                if (uuid16_names[i].num == data->val.uuid.value.uuid16) {
 
635
                                        def = &uuid16_names[i];
 
636
                                        break;
 
637
                                }
 
638
                        if (def)
 
639
                                printf("UUID16 0x%04x - %s\n", data->val.uuid.value.uuid16, def->name);
 
640
                        else
 
641
                                printf("UUID16 0x%04x\n", data->val.uuid.value.uuid16);
 
642
                        break;
 
643
                case SDP_UUID32:
 
644
                        def = NULL;
 
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];
 
650
                                                break;
 
651
                                        }
 
652
                        }
 
653
                        if (def)
 
654
                                printf("UUID32 0x%08x - %s\n", data->val.uuid.value.uuid32, def->name);
 
655
                        else
 
656
                                printf("UUID32 0x%08x\n", data->val.uuid.value.uuid32);
 
657
                        break;
 
658
                case SDP_UUID128:
 
659
                        printf("UUID128 ");
 
660
                        for (i = 0; i < 16; i++) {
 
661
                                switch (i) {
 
662
                                case 4:
 
663
                                case 6:
 
664
                                case 8:
 
665
                                case 10:
 
666
                                        printf("-");
 
667
                                        break;
 
668
                                }
 
669
                                printf("%02x", (unsigned char ) data->val.uuid.value.uuid128.data[i]);
 
670
                        }
 
671
                        printf("\n");
 
672
                        break;
 
673
                default:
 
674
                        printf("UUID type 0x%02x\n", data->val.uuid.type);
 
675
                        break;
 
676
                }
 
677
                break;
 
678
        case SDP_TEXT_STR8:
 
679
        case SDP_TEXT_STR16:
 
680
        case SDP_TEXT_STR32:
 
681
                hex = 0;
 
682
                for (i = 0; i < data->unitSize; i++) {
 
683
                        if (i == (data->unitSize - 1) && data->val.str[i] == '\0')
 
684
                                break;
 
685
                        if (!isprint(data->val.str[i])) {
 
686
                                hex = 1;
 
687
                                break;
 
688
                        }
 
689
                }
 
690
                if (hex) {
 
691
                        printf("Data");
 
692
                        for (i = 0; i < data->unitSize; i++)
 
693
                                printf(" %02x", (unsigned char) data->val.str[i]);
 
694
                } else {
 
695
                        printf("String ");
 
696
                        for (i = 0; i < data->unitSize; i++)
 
697
                                printf("%c", data->val.str[i]);
 
698
                }
 
699
                printf("\n");
 
700
                break;
 
701
        case SDP_URL_STR8:
 
702
        case SDP_URL_STR16:
 
703
        case SDP_URL_STR32:
 
704
                printf("URL %s\n", data->val.str);
 
705
                break;
 
706
        case SDP_SEQ8:
 
707
        case SDP_SEQ16:
 
708
        case SDP_SEQ32:
 
709
                printf("Sequence\n");
 
710
                print_raw_data(data->val.dataseq, indent + 1);
 
711
                break;
 
712
        case SDP_ALT8:
 
713
        case SDP_ALT16:
 
714
        case SDP_ALT32:
 
715
                printf("Alternate\n");
 
716
                print_raw_data(data->val.dataseq, indent + 1);
 
717
                break;
 
718
        default:
 
719
                printf("Unknown type 0x%02x\n", data->dtd);
 
720
                break;
 
721
        }
 
722
 
 
723
        print_raw_data(data->next, indent);
 
724
}
 
725
 
 
726
static void print_raw_attr_func(void *value, void *userData)
 
727
{
 
728
        sdp_data_t *data = (sdp_data_t *) value;
 
729
        struct attrib_def *def = NULL;
 
730
        int i;
 
731
 
 
732
        if (!data)
 
733
                return;
 
734
 
 
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];
 
739
                        break;
 
740
                }
 
741
 
 
742
        if (def)
 
743
                printf("\tAttribute 0x%04x - %s\n", data->attrId, def->name);
 
744
        else
 
745
                printf("\tAttribute 0x%04x\n", data->attrId);
 
746
 
 
747
        print_raw_data(data, 2);
 
748
}
 
749
 
 
750
static void print_raw_attr(sdp_record_t *rec)
 
751
{
 
752
        if (rec && rec->attrlist) {
 
753
                printf("Sequence\n");
 
754
                sdp_list_foreach(rec->attrlist, print_raw_attr_func, 0);
 
755
        }
 
756
}
 
757
 
 
758
/*
 
759
 * Set attributes with single values in SDP record
 
760
 * Jean II
 
761
 */
 
762
static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *value)
 
763
{
 
764
        sdp_list_t *attrid_list;
 
765
        uint32_t range = 0x0000ffff;
 
766
        sdp_record_t *rec;
 
767
        int ret;
 
768
 
 
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);
 
773
 
 
774
        if (!rec) {
 
775
                printf("Service get request failed.\n");
 
776
                return -1;
 
777
        }
 
778
 
 
779
        /* Check the type of attribute */
 
780
        if (!strncasecmp(value, "u0x", 3)) {
 
781
                /* UUID16 */
 
782
                uint16_t value_int = 0;
 
783
                uuid_t value_uuid;
 
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);
 
788
 
 
789
                sdp_attr_add_new(rec, attrib, SDP_UUID16, &value_uuid.value.uuid16);
 
790
        } else if (!strncasecmp(value, "0x", 2)) {
 
791
                /* Int */
 
792
                uint32_t value_int;
 
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);
 
796
 
 
797
                sdp_attr_add_new(rec, attrib, SDP_UINT32, &value_int);
 
798
        } else {
 
799
                /* String */
 
800
                printf("Adding attrib 0x%X string \"%s\" to record 0x%X\n",
 
801
                        attrib, value, handle);
 
802
 
 
803
                /* Add/Update our attribute to the record */
 
804
                sdp_attr_add_new(rec, attrib, SDP_TEXT_STR8, value);
 
805
        }
 
806
 
 
807
        /* Update on the server */
 
808
        ret = sdp_device_record_update(sess, &interface, rec);
 
809
        if (ret < 0)
 
810
                printf("Service Record update failed (%d).\n", errno);
 
811
        sdp_record_free(rec);
 
812
        return ret;
 
813
}
 
814
 
 
815
static struct option set_options[] = {
 
816
        { "help",       0, 0, 'h' },
 
817
        { 0, 0, 0, 0 }
 
818
};
 
819
 
 
820
static const char *set_help =
 
821
        "Usage:\n"
 
822
        "\tget record_handle attrib_id attrib_value\n";
 
823
 
 
824
/*
 
825
 * Add an attribute to an existing SDP record on the local SDP server
 
826
 */
 
827
static int cmd_setattr(int argc, char **argv)
 
828
{
 
829
        int opt, status;
 
830
        uint32_t handle;
 
831
        uint16_t attrib;
 
832
        sdp_session_t *sess;
 
833
 
 
834
        for_each_opt(opt, set_options, NULL) {
 
835
                switch(opt) {
 
836
                default:
 
837
                        printf("%s", set_help);
 
838
                        return -1;
 
839
                }
 
840
        }
 
841
 
 
842
        argc -= optind;
 
843
        argv += optind;
 
844
 
 
845
        if (argc < 3) {
 
846
                printf("%s", set_help);
 
847
                return -1;
 
848
        }
 
849
 
 
850
        /* Convert command line args */
 
851
        handle = strtoul(argv[0], NULL, 16);
 
852
        attrib = strtoul(argv[1], NULL, 16);
 
853
 
 
854
        /* Do it */
 
855
        sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
 
856
        if (!sess)
 
857
                return -1;
 
858
 
 
859
        status = set_attrib(sess, handle, attrib, argv[2]);
 
860
        sdp_close(sess);
 
861
 
 
862
        return status;
 
863
}
 
864
 
 
865
/*
 
866
 * We do only simple data sequences. Sequence of sequences is a pain ;-)
 
867
 * Jean II
 
868
 */
 
869
static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int argc, char **argv)
 
870
{
 
871
        sdp_list_t *attrid_list;
 
872
        uint32_t range = 0x0000ffff;
 
873
        sdp_record_t *rec;
 
874
        sdp_data_t *pSequenceHolder = NULL;
 
875
        void **dtdArray;
 
876
        void **valueArray;
 
877
        void **allocArray;
 
878
        uint8_t uuid16 = SDP_UUID16;
 
879
        uint8_t uint32 = SDP_UINT32;
 
880
        uint8_t str8 = SDP_TEXT_STR8;
 
881
        int i, ret = 0;
 
882
 
 
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);
 
887
 
 
888
        if (!rec) {
 
889
                printf("Service get request failed.\n");
 
890
                return -1;
 
891
        }
 
892
 
 
893
        /* Create arrays */
 
894
        dtdArray = (void **)malloc(argc * sizeof(void *));
 
895
        valueArray = (void **)malloc(argc * sizeof(void *));
 
896
        allocArray = (void **)malloc(argc * sizeof(void *));
 
897
 
 
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)) {
 
902
                        /* UUID16 */
 
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);
 
907
 
 
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)) {
 
912
                        /* Int */
 
913
                        uint32_t *value_int = (uint32_t *) malloc(sizeof(int));
 
914
                        allocArray[i] = value_int;
 
915
                        *value_int = strtoul((argv[i]) + 2, NULL, 16);
 
916
 
 
917
                        printf("Adding int 0x%X to record 0x%X\n", *value_int, handle);
 
918
                        dtdArray[i] = &uint32;
 
919
                        valueArray[i] = value_int;
 
920
                } else {
 
921
                        /* String */
 
922
                        printf("Adding string \"%s\" to record 0x%X\n", argv[i], handle);
 
923
                        dtdArray[i] = &str8;
 
924
                        valueArray[i] = argv[i];
 
925
                }
 
926
        }
 
927
 
 
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);
 
932
 
 
933
                /* Update on the server */
 
934
                ret = sdp_device_record_update(session, &interface, rec);
 
935
                if (ret < 0)
 
936
                        printf("Service Record update failed (%d).\n", errno);
 
937
        } else
 
938
                printf("Failed to create pSequenceHolder\n");
 
939
 
 
940
        /* Cleanup */
 
941
        for (i = 0; i < argc; i++)
 
942
                free(allocArray[i]);
 
943
 
 
944
        free(dtdArray);
 
945
        free(valueArray);
 
946
        free(allocArray);
 
947
 
 
948
        sdp_record_free(rec);
 
949
 
 
950
        return ret;
 
951
}
 
952
 
 
953
static struct option seq_options[] = {
 
954
        { "help",       0, 0, 'h' },
 
955
        { 0, 0, 0, 0 }
 
956
};
 
957
 
 
958
static const char *seq_help =
 
959
        "Usage:\n"
 
960
        "\tget record_handle attrib_id attrib_values\n";
 
961
 
 
962
/*
 
963
 * Add an attribute sequence to an existing SDP record
 
964
 * on the local SDP server
 
965
 */
 
966
static int cmd_setseq(int argc, char **argv)
 
967
{
 
968
        int opt, status;
 
969
        uint32_t handle;
 
970
        uint16_t attrib;
 
971
        sdp_session_t *sess;
 
972
 
 
973
        for_each_opt(opt, seq_options, NULL) {
 
974
                switch(opt) {
 
975
                default:
 
976
                        printf("%s", seq_help);
 
977
                        return -1;
 
978
                }
 
979
        }
 
980
 
 
981
        argc -= optind;
 
982
        argv += optind;
 
983
 
 
984
        if (argc < 3) {
 
985
                printf("%s", seq_help);
 
986
                return -1;
 
987
        }
 
988
 
 
989
        /* Convert command line args */
 
990
        handle = strtoul(argv[0], NULL, 16);
 
991
        attrib = strtoul(argv[1], NULL, 16);
 
992
 
 
993
        argc -= 2;
 
994
        argv += 2;
 
995
 
 
996
        /* Do it */
 
997
        sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
 
998
        if (!sess)
 
999
                return -1;
 
1000
 
 
1001
        status = set_attribseq(sess, handle, attrib, argc, argv);
 
1002
        sdp_close(sess);
 
1003
 
 
1004
        return status;
 
1005
}
 
1006
 
 
1007
static void print_service_class(void *value, void *userData)
 
1008
{
 
1009
        char ServiceClassUUID_str[MAX_LEN_SERVICECLASS_UUID_STR];
 
1010
        uuid_t *uuid = (uuid_t *)value;
 
1011
 
 
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);
 
1016
        else
 
1017
                printf("  UUID 128: %s\n", UUID_str);
 
1018
}
 
1019
 
 
1020
static void print_service_desc(void *value, void *user)
 
1021
{
 
1022
        char str[MAX_LEN_PROTOCOL_UUID_STR];
 
1023
        sdp_data_t *p = (sdp_data_t *)value, *s;
 
1024
        int i = 0, proto = 0;
 
1025
 
 
1026
        for (; p; p = p->next, i++) {
 
1027
                switch (p->dtd) {
 
1028
                case SDP_UUID16:
 
1029
                case SDP_UUID32:
 
1030
                case SDP_UUID128:
 
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);
 
1035
                        break;
 
1036
                case SDP_UINT8:
 
1037
                        if (proto == RFCOMM_UUID)
 
1038
                                printf("    Channel: %d\n", p->val.uint8);
 
1039
                        else
 
1040
                                printf("    uint8: 0x%x\n", p->val.uint8);
 
1041
                        break;
 
1042
                case SDP_UINT16:
 
1043
                        if (proto == L2CAP_UUID) {
 
1044
                                if (i == 1)
 
1045
                                        printf("    PSM: %d\n", p->val.uint16);
 
1046
                                else
 
1047
                                        printf("    Version: 0x%04x\n", p->val.uint16);
 
1048
                        } else if (proto == BNEP_UUID)
 
1049
                                if (i == 1)
 
1050
                                        printf("    Version: 0x%04x\n", p->val.uint16);
 
1051
                                else
 
1052
                                        printf("    uint16: 0x%x\n", p->val.uint16);
 
1053
                        else
 
1054
                                printf("    uint16: 0x%x\n", p->val.uint16);
 
1055
                        break;
 
1056
                case SDP_SEQ16:
 
1057
                        printf("    SEQ16:");
 
1058
                        for (s = p->val.dataseq; s; s = s->next)
 
1059
                                printf(" %x", s->val.uint16);
 
1060
                        printf("\n");
 
1061
                        break;
 
1062
                case SDP_SEQ8:
 
1063
                        printf("    SEQ8:");
 
1064
                        for (s = p->val.dataseq; s; s = s->next)
 
1065
                                printf(" %x", s->val.uint8);
 
1066
                        printf("\n");
 
1067
                        break;
 
1068
                default:
 
1069
                        printf("    FIXME: dtd=0%x\n", p->dtd);
 
1070
                        break;
 
1071
                }
 
1072
        }
 
1073
}
 
1074
 
 
1075
static void print_lang_attr(void *value, void *user)
 
1076
{
 
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);
 
1081
}
 
1082
 
 
1083
static void print_access_protos(void *value, void *userData)
 
1084
{
 
1085
        sdp_list_t *protDescSeq = (sdp_list_t *)value;
 
1086
        sdp_list_foreach(protDescSeq, print_service_desc, 0);
 
1087
}
 
1088
 
 
1089
static void print_profile_desc(void *value, void *userData)
 
1090
{
 
1091
        sdp_profile_desc_t *desc = (sdp_profile_desc_t *)value;
 
1092
        char str[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR];
 
1093
 
 
1094
        sdp_uuid2strn(&desc->uuid, UUID_str, MAX_LEN_UUID_STR);
 
1095
        sdp_profile_uuid2strn(&desc->uuid, str, MAX_LEN_PROFILEDESCRIPTOR_UUID_STR);
 
1096
 
 
1097
        printf("  \"%s\" (0x%s)\n", str, UUID_str);
 
1098
        if (desc->version)
 
1099
                printf("    Version: 0x%04x\n", desc->version);
 
1100
}
 
1101
 
 
1102
/*
 
1103
 * Parse a SDP record in user friendly form.
 
1104
 */
 
1105
static void print_service_attr(sdp_record_t *rec)
 
1106
{
 
1107
        sdp_list_t *list = 0, *proto = 0;
 
1108
 
 
1109
        sdp_record_print(rec);
 
1110
 
 
1111
        printf("Service RecHandle: 0x%x\n", rec->handle);
 
1112
 
 
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);
 
1117
        }
 
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);
 
1123
        }
 
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);
 
1128
        }
 
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);
 
1133
        }
 
1134
}
 
1135
 
 
1136
/*
 
1137
 * Support for Service (de)registration
 
1138
 */
 
1139
typedef struct {
 
1140
        uint32_t handle;
 
1141
        char *name;
 
1142
        char *provider;
 
1143
        char *desc;
 
1144
        unsigned int class;
 
1145
        unsigned int profile;
 
1146
        uint16_t psm;
 
1147
        uint8_t channel;
 
1148
        uint8_t network;
 
1149
} svc_info_t;
 
1150
 
 
1151
static int add_sp(sdp_session_t *session, svc_info_t *si)
 
1152
{
 
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;
 
1159
        int ret = 0;
 
1160
 
 
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);
 
1167
 
 
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);
 
1172
 
 
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);
 
1178
 
 
1179
        sdp_uuid16_create(&l2cap, L2CAP_UUID);
 
1180
        proto[0] = sdp_list_append(0, &l2cap);
 
1181
        apseq = sdp_list_append(0, proto[0]);
 
1182
 
 
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]);
 
1188
 
 
1189
        aproto = sdp_list_append(0, apseq);
 
1190
        sdp_set_access_protos(&record, aproto);
 
1191
 
 
1192
        sdp_add_lang_attr(&record);
 
1193
 
 
1194
        sdp_set_info_attr(&record, "Serial Port", "BlueZ", "COM Port");
 
1195
 
 
1196
        sdp_set_url_attr(&record, "http://www.bluez.org/",
 
1197
                        "http://www.bluez.org/", "http://www.bluez.org/");
 
1198
 
 
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);
 
1203
 
 
1204
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1205
                printf("Service Record registration failed\n");
 
1206
                ret = -1;
 
1207
                goto end;
 
1208
        }
 
1209
 
 
1210
        printf("Serial Port service registered\n");
 
1211
 
 
1212
end:
 
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);
 
1218
 
 
1219
        return ret;
 
1220
}
 
1221
 
 
1222
static int add_dun(sdp_session_t *session, svc_info_t *si)
 
1223
{
 
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;
 
1231
        int ret = 0;
 
1232
 
 
1233
        memset(&record, 0, sizeof(sdp_record_t));
 
1234
        record.handle = si->handle;
 
1235
 
 
1236
        sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP);
 
1237
        root = sdp_list_append(0, &rootu);
 
1238
        sdp_set_browse_groups(&record, root);
 
1239
 
 
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);
 
1245
 
 
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);
 
1250
 
 
1251
        sdp_uuid16_create(&l2cap, L2CAP_UUID);
 
1252
        proto[0] = sdp_list_append(0, &l2cap);
 
1253
        apseq = sdp_list_append(0, proto[0]);
 
1254
 
 
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]);
 
1260
 
 
1261
        aproto = sdp_list_append(0, apseq);
 
1262
        sdp_set_access_protos(&record, aproto);
 
1263
 
 
1264
        sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0);
 
1265
 
 
1266
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1267
                printf("Service Record registration failed\n");
 
1268
                ret = -1;
 
1269
                goto end;
 
1270
        }
 
1271
 
 
1272
        printf("Dial-Up Networking service registered\n");
 
1273
 
 
1274
end:
 
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);
 
1280
 
 
1281
        return ret;
 
1282
}
 
1283
 
 
1284
static int add_fax(sdp_session_t *session, svc_info_t *si)
 
1285
{
 
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;
 
1293
        int ret = 0;
 
1294
 
 
1295
        memset(&record, 0, sizeof(sdp_record_t));
 
1296
        record.handle = si->handle;
 
1297
 
 
1298
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1299
        root = sdp_list_append(0, &root_uuid);
 
1300
        sdp_set_browse_groups(&record, root);
 
1301
 
 
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);
 
1307
 
 
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);
 
1312
 
 
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]);
 
1316
 
 
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]);
 
1322
 
 
1323
        aproto = sdp_list_append(0, apseq);
 
1324
        sdp_set_access_protos(&record, aproto);
 
1325
 
 
1326
        sdp_set_info_attr(&record, "Fax", 0, 0);
 
1327
 
 
1328
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1329
                printf("Service Record registration failed\n");
 
1330
                ret = -1;
 
1331
                goto end;
 
1332
        }
 
1333
        printf("Fax service registered\n");
 
1334
end:
 
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);
 
1340
        return ret;
 
1341
}
 
1342
 
 
1343
static int add_lan(sdp_session_t *session, svc_info_t *si)
 
1344
{
 
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;
 
1352
        int ret = 0;
 
1353
 
 
1354
        memset(&record, 0, sizeof(sdp_record_t));
 
1355
        record.handle = si->handle;
 
1356
 
 
1357
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1358
        root = sdp_list_append(0, &root_uuid);
 
1359
        sdp_set_browse_groups(&record, root);
 
1360
 
 
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);
 
1364
 
 
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);
 
1369
 
 
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]);
 
1373
 
 
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]);
 
1379
 
 
1380
        aproto = sdp_list_append(0, apseq);
 
1381
        sdp_set_access_protos(&record, aproto);
 
1382
 
 
1383
        sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0);
 
1384
 
 
1385
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1386
                printf("Service Record registration failed\n");
 
1387
                ret = -1;
 
1388
                goto end;
 
1389
        }
 
1390
 
 
1391
        printf("LAN Access service registered\n");
 
1392
 
 
1393
end:
 
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);
 
1399
 
 
1400
        return ret;
 
1401
}
 
1402
 
 
1403
static int add_headset(sdp_session_t *session, svc_info_t *si)
 
1404
{
 
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;
 
1412
        int ret = 0;
 
1413
 
 
1414
        memset(&record, 0, sizeof(sdp_record_t));
 
1415
        record.handle = si->handle;
 
1416
 
 
1417
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1418
        root = sdp_list_append(0, &root_uuid);
 
1419
        sdp_set_browse_groups(&record, root);
 
1420
 
 
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);
 
1426
 
 
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);
 
1431
 
 
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]);
 
1435
 
 
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]);
 
1441
 
 
1442
        aproto = sdp_list_append(0, apseq);
 
1443
        sdp_set_access_protos(&record, aproto);
 
1444
 
 
1445
        sdp_set_info_attr(&record, "Headset", 0, 0);
 
1446
 
 
1447
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1448
                printf("Service Record registration failed\n");
 
1449
                ret = -1;
 
1450
                goto end;
 
1451
        }
 
1452
 
 
1453
        printf("Headset service registered\n");
 
1454
 
 
1455
end:
 
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);
 
1461
 
 
1462
        return ret;
 
1463
}
 
1464
 
 
1465
static int add_headset_ag(sdp_session_t *session, svc_info_t *si)
 
1466
{
 
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);
 
1476
        int ret = 0;
 
1477
 
 
1478
        memset(&record, 0, sizeof(sdp_record_t));
 
1479
        record.handle = si->handle;
 
1480
 
 
1481
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1482
        root = sdp_list_append(0, &root_uuid);
 
1483
        sdp_set_browse_groups(&record, root);
 
1484
 
 
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);
 
1490
 
 
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);
 
1495
 
 
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]);
 
1499
 
 
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]);
 
1505
 
 
1506
        aproto = sdp_list_append(0, apseq);
 
1507
        sdp_set_access_protos(&record, aproto);
 
1508
 
 
1509
        sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
 
1510
 
 
1511
        sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
 
1512
 
 
1513
        if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
 
1514
                printf("Service Record registration failed\n");
 
1515
                ret = -1;
 
1516
                goto end;
 
1517
        }
 
1518
 
 
1519
        printf("Headset AG service registered\n");
 
1520
 
 
1521
end:
 
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);
 
1527
 
 
1528
        return ret;
 
1529
}
 
1530
 
 
1531
static int add_handsfree(sdp_session_t *session, svc_info_t *si)
 
1532
{
 
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;
 
1541
        int ret = 0;
 
1542
 
 
1543
        memset(&record, 0, sizeof(sdp_record_t));
 
1544
        record.handle = si->handle;
 
1545
 
 
1546
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1547
        root = sdp_list_append(0, &root_uuid);
 
1548
        sdp_set_browse_groups(&record, root);
 
1549
 
 
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);
 
1555
 
 
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);
 
1560
 
 
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]);
 
1564
 
 
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]);
 
1570
 
 
1571
        features = sdp_data_alloc(SDP_UINT16, &u16);
 
1572
        sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
 
1573
 
 
1574
        aproto = sdp_list_append(0, apseq);
 
1575
        sdp_set_access_protos(&record, aproto);
 
1576
 
 
1577
        sdp_set_info_attr(&record, "Handsfree", 0, 0);
 
1578
 
 
1579
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1580
                printf("Service Record registration failed\n");
 
1581
                ret = -1;
 
1582
                goto end;
 
1583
        }
 
1584
 
 
1585
        printf("Handsfree service registered\n");
 
1586
 
 
1587
end:
 
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);
 
1593
 
 
1594
        return ret;
 
1595
}
 
1596
 
 
1597
static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si)
 
1598
{
 
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);
 
1609
        int ret = 0;
 
1610
 
 
1611
        memset(&record, 0, sizeof(sdp_record_t));
 
1612
        record.handle = si->handle;
 
1613
 
 
1614
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1615
        root = sdp_list_append(0, &root_uuid);
 
1616
        sdp_set_browse_groups(&record, root);
 
1617
 
 
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);
 
1623
 
 
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);
 
1628
 
 
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]);
 
1632
 
 
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]);
 
1638
 
 
1639
        features = sdp_data_alloc(SDP_UINT16, &u16);
 
1640
        sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
 
1641
 
 
1642
        aproto = sdp_list_append(0, apseq);
 
1643
        sdp_set_access_protos(&record, aproto);
 
1644
 
 
1645
        sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
 
1646
 
 
1647
        sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
 
1648
 
 
1649
        if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
 
1650
                printf("Service Record registration failed\n");
 
1651
                ret = -1;
 
1652
                goto end;
 
1653
        }
 
1654
 
 
1655
        printf("Handsfree AG service registered\n");
 
1656
 
 
1657
end:
 
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);
 
1663
 
 
1664
        return ret;
 
1665
}
 
1666
 
 
1667
static int add_simaccess(sdp_session_t *session, svc_info_t *si)
 
1668
{
 
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;
 
1677
        int ret = 0;
 
1678
 
 
1679
        memset((void *)&record, 0, sizeof(sdp_record_t));
 
1680
        record.handle = si->handle;
 
1681
 
 
1682
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1683
        root = sdp_list_append(0, &root_uuid);
 
1684
        sdp_set_browse_groups(&record, root);
 
1685
 
 
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);
 
1691
 
 
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);
 
1696
 
 
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]);
 
1700
 
 
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]);
 
1706
 
 
1707
        features = sdp_data_alloc(SDP_UINT16, &u16);
 
1708
        sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
 
1709
 
 
1710
        aproto = sdp_list_append(0, apseq);
 
1711
        sdp_set_access_protos(&record, aproto);
 
1712
 
 
1713
        sdp_set_info_attr(&record, "SIM Access", 0, 0);
 
1714
 
 
1715
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1716
                printf("Service Record registration failed\n");
 
1717
                ret = -1;
 
1718
                goto end;
 
1719
        }
 
1720
 
 
1721
        printf("SIM Access service registered\n");
 
1722
 
 
1723
end:
 
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);
 
1729
 
 
1730
        return ret;
 
1731
}
 
1732
 
 
1733
static int add_opush(sdp_session_t *session, svc_info_t *si)
 
1734
{
 
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)];
 
1744
        unsigned int i;
 
1745
        uint8_t dtd = SDP_UINT8;
 
1746
        sdp_data_t *sflist;
 
1747
        int ret = 0;
 
1748
 
 
1749
        memset(&record, 0, sizeof(sdp_record_t));
 
1750
        record.handle = si->handle;
 
1751
 
 
1752
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1753
        root = sdp_list_append(0, &root_uuid);
 
1754
        sdp_set_browse_groups(&record, root);
 
1755
 
 
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);
 
1759
 
 
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);
 
1764
 
 
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]);
 
1768
 
 
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]);
 
1774
 
 
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]);
 
1778
 
 
1779
        aproto = sdp_list_append(0, apseq);
 
1780
        sdp_set_access_protos(&record, aproto);
 
1781
 
 
1782
        for (i = 0; i < sizeof(formats); i++) {
 
1783
                dtds[i] = &dtd;
 
1784
                values[i] = &formats[i];
 
1785
        }
 
1786
        sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
 
1787
        sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
 
1788
 
 
1789
        sdp_set_info_attr(&record, "OBEX Object Push", 0, 0);
 
1790
 
 
1791
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1792
                printf("Service Record registration failed\n");
 
1793
                ret = -1;
 
1794
                goto end;
 
1795
        }
 
1796
 
 
1797
        printf("OBEX Object Push service registered\n");
 
1798
 
 
1799
end:
 
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);
 
1806
 
 
1807
        return ret;
 
1808
}
 
1809
 
 
1810
static int add_pbap(sdp_session_t *session, svc_info_t *si)
 
1811
{
 
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;
 
1821
        sdp_data_t *sflist;
 
1822
        int ret = 0;
 
1823
 
 
1824
        memset(&record, 0, sizeof(sdp_record_t));
 
1825
        record.handle = si->handle;
 
1826
 
 
1827
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1828
        root = sdp_list_append(0, &root_uuid);
 
1829
        sdp_set_browse_groups(&record, root);
 
1830
 
 
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);
 
1834
 
 
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);
 
1839
 
 
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]);
 
1843
 
 
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]);
 
1849
 
 
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]);
 
1853
 
 
1854
        aproto = sdp_list_append(0, apseq);
 
1855
        sdp_set_access_protos(&record, aproto);
 
1856
 
 
1857
        sflist = sdp_data_alloc(dtd,formats);
 
1858
        sdp_attr_add(&record, SDP_ATTR_SUPPORTED_REPOSITORIES, sflist);
 
1859
 
 
1860
        sdp_set_info_attr(&record, "OBEX Phonebook Access Server", 0, 0);
 
1861
 
 
1862
        if (sdp_device_record_register(session, &interface, &record,
 
1863
                        SDP_RECORD_PERSIST) < 0) {
 
1864
                printf("Service Record registration failed\n");
 
1865
                ret = -1;
 
1866
                goto end;
 
1867
        }
 
1868
 
 
1869
        printf("PBAP service registered\n");
 
1870
 
 
1871
end:
 
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);
 
1878
 
 
1879
        return ret;
 
1880
}
 
1881
 
 
1882
static int add_ftp(sdp_session_t *session, svc_info_t *si)
 
1883
{
 
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;
 
1891
        int ret = 0;
 
1892
 
 
1893
        memset(&record, 0, sizeof(sdp_record_t));
 
1894
        record.handle = si->handle;
 
1895
 
 
1896
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1897
        root = sdp_list_append(0, &root_uuid);
 
1898
        sdp_set_browse_groups(&record, root);
 
1899
 
 
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);
 
1903
 
 
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);
 
1908
 
 
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]);
 
1912
 
 
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]);
 
1918
 
 
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]);
 
1922
 
 
1923
        aproto = sdp_list_append(0, apseq);
 
1924
        sdp_set_access_protos(&record, aproto);
 
1925
 
 
1926
        sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0);
 
1927
 
 
1928
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1929
                printf("Service Record registration failed\n");
 
1930
                ret = -1;
 
1931
                goto end;
 
1932
        }
 
1933
 
 
1934
        printf("OBEX File Transfer service registered\n");
 
1935
 
 
1936
end:
 
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);
 
1943
 
 
1944
        return ret;
 
1945
}
 
1946
 
 
1947
static int add_directprint(sdp_session_t *session, svc_info_t *si)
 
1948
{
 
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;
 
1956
        int ret = 0;
 
1957
 
 
1958
        memset(&record, 0, sizeof(sdp_record_t));
 
1959
        record.handle = si->handle;
 
1960
 
 
1961
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
1962
        root = sdp_list_append(0, &root_uuid);
 
1963
        sdp_set_browse_groups(&record, root);
 
1964
 
 
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);
 
1968
 
 
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);
 
1973
 
 
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]);
 
1977
 
 
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]);
 
1983
 
 
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]);
 
1987
 
 
1988
        aproto = sdp_list_append(0, apseq);
 
1989
        sdp_set_access_protos(&record, aproto);
 
1990
 
 
1991
        sdp_set_info_attr(&record, "Direct Printing", 0, 0);
 
1992
 
 
1993
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
1994
                printf("Service Record registration failed\n");
 
1995
                ret = -1;
 
1996
                goto end;
 
1997
        }
 
1998
 
 
1999
        printf("Direct Printing service registered\n");
 
2000
 
 
2001
end:
 
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);
 
2008
 
 
2009
        return ret;
 
2010
}
 
2011
 
 
2012
static int add_nap(sdp_session_t *session, svc_info_t *si)
 
2013
{
 
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;
 
2021
        int ret = 0;
 
2022
 
 
2023
        memset(&record, 0, sizeof(sdp_record_t));
 
2024
        record.handle = si->handle;
 
2025
 
 
2026
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2027
        root = sdp_list_append(0, &root_uuid);
 
2028
        sdp_set_browse_groups(&record, root);
 
2029
 
 
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);
 
2033
 
 
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);
 
2038
 
 
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]);
 
2044
 
 
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);
 
2049
 
 
2050
        {
 
2051
                uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 };
 
2052
                sdp_data_t *head, *pseq;
 
2053
                int p;
 
2054
 
 
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);
 
2058
                }
 
2059
                pseq = sdp_data_alloc(SDP_SEQ16, head);
 
2060
                proto[1] = sdp_list_append(proto[1], pseq);
 
2061
        }
 
2062
 
 
2063
        apseq = sdp_list_append(apseq, proto[1]);
 
2064
 
 
2065
        aproto = sdp_list_append(0, apseq);
 
2066
        sdp_set_access_protos(&record, aproto);
 
2067
 
 
2068
        sdp_set_info_attr(&record, "Network Access Point Service", 0, 0);
 
2069
 
 
2070
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2071
                printf("Service Record registration failed\n");
 
2072
                ret = -1;
 
2073
                goto end;
 
2074
        }
 
2075
 
 
2076
        printf("NAP service registered\n");
 
2077
 
 
2078
end:
 
2079
        sdp_data_free(version);
 
2080
        sdp_data_free(psm);
 
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);
 
2085
 
 
2086
        return ret;
 
2087
}
 
2088
 
 
2089
static int add_gn(sdp_session_t *session, svc_info_t *si)
 
2090
{
 
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;
 
2098
        int ret = 0;
 
2099
 
 
2100
        memset(&record, 0, sizeof(sdp_record_t));
 
2101
        record.handle = si->handle;
 
2102
 
 
2103
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2104
        root = sdp_list_append(0, &root_uuid);
 
2105
        sdp_set_browse_groups(&record, root);
 
2106
 
 
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);
 
2110
 
 
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);
 
2115
 
 
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]);
 
2121
 
 
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]);
 
2127
 
 
2128
        aproto = sdp_list_append(0, apseq);
 
2129
        sdp_set_access_protos(&record, aproto);
 
2130
 
 
2131
        sdp_set_info_attr(&record, "Group Network Service", 0, 0);
 
2132
 
 
2133
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2134
                printf("Service Record registration failed\n");
 
2135
                ret = -1;
 
2136
                goto end;
 
2137
        }
 
2138
 
 
2139
        printf("GN service registered\n");
 
2140
 
 
2141
end:
 
2142
        sdp_data_free(version);
 
2143
        sdp_data_free(psm);
 
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);
 
2148
 
 
2149
        return ret;
 
2150
}
 
2151
 
 
2152
static int add_panu(sdp_session_t *session, svc_info_t *si)
 
2153
{
 
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;
 
2161
        int ret = 0;
 
2162
 
 
2163
        memset(&record, 0, sizeof(sdp_record_t));
 
2164
        record.handle = si->handle;
 
2165
 
 
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);
 
2170
 
 
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);
 
2175
 
 
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);
 
2181
 
 
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]);
 
2187
 
 
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]);
 
2193
 
 
2194
        aproto = sdp_list_append(NULL, apseq);
 
2195
        sdp_set_access_protos(&record, aproto);
 
2196
 
 
2197
        sdp_set_info_attr(&record, "PAN User", NULL, NULL);
 
2198
 
 
2199
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2200
                printf("Service Record registration failed\n");
 
2201
                ret = -1;
 
2202
                goto end;
 
2203
        }
 
2204
 
 
2205
        printf("PANU service registered\n");
 
2206
 
 
2207
end:
 
2208
        sdp_data_free(version);
 
2209
        sdp_data_free(psm);
 
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);
 
2214
 
 
2215
        return ret;
 
2216
}
 
2217
 
 
2218
static int add_hid_keyb(sdp_session_t *session, svc_info_t *si)
 
2219
{
 
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;
 
2226
        unsigned int i;
 
2227
        uint8_t dtd = SDP_UINT16;
 
2228
        uint8_t dtd2 = SDP_UINT8;
 
2229
        uint8_t dtd_data = SDP_TEXT_STR8;
 
2230
        void *dtds[2];
 
2231
        void *values[2];
 
2232
        void *dtds2[2];
 
2233
        void *values2[2];
 
2234
        int leng[2];
 
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
 
2246
                0x05, 0x07, // max
 
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
 
2254
                0x75, 0x08,
 
2255
                0x95, 0x01,
 
2256
                0x81, 0x01,
 
2257
                0x75, 0x01,
 
2258
                0x95, 0x05,
 
2259
                0x05, 0x08,
 
2260
                0x19, 0x01,
 
2261
                0x29, 0x05,
 
2262
                0x91, 0x02,
 
2263
                0x75, 0x03,
 
2264
                0x95, 0x01,
 
2265
                0x91, 0x01,
 
2266
                0x75, 0x08,
 
2267
                0x95, 0x06,
 
2268
                0x15, 0x00,
 
2269
                0x26, 0xff,
 
2270
                0x00, 0x05,
 
2271
                0x07, 0x19,
 
2272
                0x00, 0x2a,
 
2273
                0xff, 0x00,
 
2274
                0x81, 0x00,
 
2275
                0x75, 0x01,
 
2276
                0x95, 0x01,
 
2277
                0x15, 0x00,
 
2278
                0x25, 0x01,
 
2279
                0x05, 0x0c,
 
2280
                0x09, 0xb8,
 
2281
                0x81, 0x06,
 
2282
                0x09, 0xe2,
 
2283
                0x81, 0x06,
 
2284
                0x09, 0xe9,
 
2285
                0x81, 0x02,
 
2286
                0x09, 0xea,
 
2287
                0x81, 0x02,
 
2288
                0x75, 0x01,
 
2289
                0x95, 0x04,
 
2290
                0x81, 0x01,
 
2291
                0xc0         // end tag
 
2292
        };
 
2293
 
 
2294
        memset(&record, 0, sizeof(sdp_record_t));
 
2295
        record.handle = si->handle;
 
2296
 
 
2297
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2298
        root = sdp_list_append(0, &root_uuid);
 
2299
        sdp_set_browse_groups(&record, root);
 
2300
 
 
2301
        sdp_add_lang_attr(&record);
 
2302
 
 
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);
 
2306
 
 
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);
 
2311
 
 
2312
        /* protocols */
 
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]);
 
2318
 
 
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]);
 
2322
 
 
2323
        aproto = sdp_list_append(0, apseq);
 
2324
        sdp_set_access_protos(&record, aproto);
 
2325
 
 
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]);
 
2331
 
 
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]);
 
2335
 
 
2336
        aproto = sdp_list_append(0, apseq);
 
2337
        sdp_set_add_access_protos(&record, aproto);
 
2338
 
 
2339
        sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL);
 
2340
 
 
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]);
 
2345
 
 
2346
        dtds[0] = &dtd2;
 
2347
        values[0] = &hid_spec_type;
 
2348
        dtds[1] = &dtd_data;
 
2349
        values[1] = (uint8_t *) hid_spec;
 
2350
        leng[0] = 0;
 
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);
 
2355
 
 
2356
        for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
 
2357
                dtds2[i] = &dtd;
 
2358
                values2[i] = &hid_attr_lang[i];
 
2359
        }
 
2360
 
 
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);
 
2364
 
 
2365
        sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]);
 
2366
 
 
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]);
 
2370
 
 
2371
        if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
 
2372
                printf("Service Record registration failed\n");
 
2373
                return -1;
 
2374
        }
 
2375
 
 
2376
        printf("HID keyboard service registered\n");
 
2377
 
 
2378
        return 0;
 
2379
}
 
2380
 
 
2381
static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si)
 
2382
{
 
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;
 
2389
        unsigned int i;
 
2390
        uint8_t dtd = SDP_UINT16;
 
2391
        uint8_t dtd2 = SDP_UINT8;
 
2392
        uint8_t dtd_data = SDP_TEXT_STR8;
 
2393
        void *dtds[2];
 
2394
        void *values[2];
 
2395
        void *dtds2[2];
 
2396
        void *values2[2];
 
2397
        int leng[2];
 
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,
 
2435
                0xc0, 0x00
 
2436
        };
 
2437
 
 
2438
        memset(&record, 0, sizeof(sdp_record_t));
 
2439
        record.handle = si->handle;
 
2440
 
 
2441
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2442
        root = sdp_list_append(NULL, &root_uuid);
 
2443
        sdp_set_browse_groups(&record, root);
 
2444
 
 
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);
 
2448
 
 
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);
 
2453
 
 
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]);
 
2459
 
 
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]);
 
2463
 
 
2464
        aproto = sdp_list_append(0, apseq);
 
2465
        sdp_set_access_protos(&record, aproto);
 
2466
 
 
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]);
 
2471
 
 
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]);
 
2475
 
 
2476
        aproto = sdp_list_append(0, apseq);
 
2477
        sdp_set_add_access_protos(&record, aproto);
 
2478
 
 
2479
        sdp_add_lang_attr(&record);
 
2480
 
 
2481
        sdp_set_info_attr(&record, "Nintendo RVL-CNT-01",
 
2482
                                        "Nintendo", "Nintendo RVL-CNT-01");
 
2483
 
 
2484
        sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
 
2485
                                                SDP_UINT16, &hid_release);
 
2486
 
 
2487
        sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION,
 
2488
                                                SDP_UINT16, &parser_version);
 
2489
 
 
2490
        sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS,
 
2491
                                                SDP_UINT8, &subclass);
 
2492
 
 
2493
        sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE,
 
2494
                                                SDP_UINT8, &country);
 
2495
 
 
2496
        sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE,
 
2497
                                                SDP_BOOL, &virtual_cable);
 
2498
 
 
2499
        sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE,
 
2500
                                                SDP_BOOL, &reconnect);
 
2501
 
 
2502
        dtds[0] = &dtd2;
 
2503
        values[0] = &hid_spec_type;
 
2504
        dtds[1] = &dtd_data;
 
2505
        values[1] = (uint8_t *) hid_spec;
 
2506
        leng[0] = 0;
 
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);
 
2511
 
 
2512
        for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
 
2513
                dtds2[i] = &dtd;
 
2514
                values2[i] = &hid_attr_lang[i];
 
2515
        }
 
2516
 
 
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);
 
2520
 
 
2521
        sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE,
 
2522
                                                SDP_BOOL, &sdp_disable);
 
2523
 
 
2524
        sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER,
 
2525
                                                SDP_BOOL, &battery);
 
2526
 
 
2527
        sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP,
 
2528
                                                SDP_BOOL, &remote_wakeup);
 
2529
 
 
2530
        sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION,
 
2531
                                                SDP_UINT16, &profile_version);
 
2532
 
 
2533
        sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT,
 
2534
                                                SDP_UINT16, &superv_timeout);
 
2535
 
 
2536
        sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE,
 
2537
                                                SDP_BOOL, &norm_connect);
 
2538
 
 
2539
        sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE,
 
2540
                                                SDP_BOOL, &boot_device);
 
2541
 
 
2542
        if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
 
2543
                printf("Service Record registration failed\n");
 
2544
                return -1;
 
2545
        }
 
2546
 
 
2547
        printf("Wii-Mote service registered\n");
 
2548
 
 
2549
        return 0;
 
2550
}
 
2551
 
 
2552
static int add_cip(sdp_session_t *session, svc_info_t *si)
 
2553
{
 
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);
 
2562
        int ret = 0;
 
2563
 
 
2564
        memset(&record, 0, sizeof(sdp_record_t));
 
2565
        record.handle = si->handle;
 
2566
 
 
2567
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2568
        root = sdp_list_append(0, &root_uuid);
 
2569
        sdp_set_browse_groups(&record, root);
 
2570
 
 
2571
        sdp_uuid16_create(&cip, CIP_SVCLASS_ID);
 
2572
        svclass_id = sdp_list_append(0, &cip);
 
2573
        sdp_set_service_classes(&record, svclass_id);
 
2574
 
 
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);
 
2579
 
 
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]);
 
2585
 
 
2586
        sdp_uuid16_create(&cmtp, CMTP_UUID);
 
2587
        proto[1] = sdp_list_append(0, &cmtp);
 
2588
        apseq = sdp_list_append(apseq, proto[1]);
 
2589
 
 
2590
        aproto = sdp_list_append(0, apseq);
 
2591
        sdp_set_access_protos(&record, aproto);
 
2592
 
 
2593
        sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
 
2594
 
 
2595
        sdp_set_info_attr(&record, "Common ISDN Access", 0, 0);
 
2596
 
 
2597
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2598
                printf("Service Record registration failed\n");
 
2599
                ret = -1;
 
2600
                goto end;
 
2601
        }
 
2602
 
 
2603
        printf("CIP service registered\n");
 
2604
 
 
2605
end:
 
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);
 
2611
 
 
2612
        return ret;
 
2613
}
 
2614
 
 
2615
static int add_ctp(sdp_session_t *session, svc_info_t *si)
 
2616
{
 
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);
 
2624
        int ret = 0;
 
2625
 
 
2626
        memset(&record, 0, sizeof(sdp_record_t));
 
2627
        record.handle = si->handle;
 
2628
 
 
2629
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2630
        root = sdp_list_append(0, &root_uuid);
 
2631
        sdp_set_browse_groups(&record, root);
 
2632
 
 
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);
 
2636
 
 
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);
 
2641
 
 
2642
        sdp_uuid16_create(&l2cap, L2CAP_UUID);
 
2643
        proto[0] = sdp_list_append(0, &l2cap);
 
2644
        apseq = sdp_list_append(0, proto[0]);
 
2645
 
 
2646
        sdp_uuid16_create(&tcsbin, TCS_BIN_UUID);
 
2647
        proto[1] = sdp_list_append(0, &tcsbin);
 
2648
        apseq = sdp_list_append(apseq, proto[1]);
 
2649
 
 
2650
        aproto = sdp_list_append(0, apseq);
 
2651
        sdp_set_access_protos(&record, aproto);
 
2652
 
 
2653
        sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
 
2654
 
 
2655
        sdp_set_info_attr(&record, "Cordless Telephony", 0, 0);
 
2656
 
 
2657
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2658
                printf("Service Record registration failed\n");
 
2659
                ret = -1;
 
2660
                goto end;
 
2661
        }
 
2662
 
 
2663
        printf("CTP service registered\n");
 
2664
 
 
2665
end:
 
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);
 
2671
 
 
2672
        return ret;
 
2673
}
 
2674
 
 
2675
static int add_a2source(sdp_session_t *session, svc_info_t *si)
 
2676
{
 
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;
 
2684
        int ret = 0;
 
2685
 
 
2686
        memset(&record, 0, sizeof(sdp_record_t));
 
2687
        record.handle = si->handle;
 
2688
 
 
2689
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2690
        root = sdp_list_append(0, &root_uuid);
 
2691
        sdp_set_browse_groups(&record, root);
 
2692
 
 
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);
 
2696
 
 
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);
 
2701
 
 
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]);
 
2707
 
 
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]);
 
2713
 
 
2714
        aproto = sdp_list_append(0, apseq);
 
2715
        sdp_set_access_protos(&record, aproto);
 
2716
 
 
2717
        sdp_set_info_attr(&record, "Audio Source", 0, 0);
 
2718
 
 
2719
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2720
                printf("Service Record registration failed\n");
 
2721
                ret = -1;
 
2722
                goto done;
 
2723
        }
 
2724
 
 
2725
        printf("Audio source service registered\n");
 
2726
 
 
2727
done:
 
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);
 
2732
 
 
2733
        return ret;
 
2734
}
 
2735
 
 
2736
static int add_a2sink(sdp_session_t *session, svc_info_t *si)
 
2737
{
 
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;
 
2745
        int ret = 0;
 
2746
 
 
2747
        memset(&record, 0, sizeof(sdp_record_t));
 
2748
        record.handle = si->handle;
 
2749
 
 
2750
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2751
        root = sdp_list_append(0, &root_uuid);
 
2752
        sdp_set_browse_groups(&record, root);
 
2753
 
 
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);
 
2757
 
 
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);
 
2762
 
 
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]);
 
2768
 
 
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]);
 
2774
 
 
2775
        aproto = sdp_list_append(0, apseq);
 
2776
        sdp_set_access_protos(&record, aproto);
 
2777
 
 
2778
        sdp_set_info_attr(&record, "Audio Sink", 0, 0);
 
2779
 
 
2780
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2781
                printf("Service Record registration failed\n");
 
2782
                ret = -1;
 
2783
                goto done;
 
2784
        }
 
2785
 
 
2786
        printf("Audio sink service registered\n");
 
2787
 
 
2788
done:
 
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);
 
2793
 
 
2794
        return ret;
 
2795
}
 
2796
 
 
2797
static int add_avrct(sdp_session_t *session, svc_info_t *si)
 
2798
{
 
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;
 
2806
        int ret = 0;
 
2807
 
 
2808
        memset(&record, 0, sizeof(sdp_record_t));
 
2809
        record.handle = si->handle;
 
2810
 
 
2811
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2812
        root = sdp_list_append(0, &root_uuid);
 
2813
        sdp_set_browse_groups(&record, root);
 
2814
 
 
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);
 
2818
 
 
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);
 
2823
 
 
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]);
 
2829
 
 
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]);
 
2835
 
 
2836
        aproto = sdp_list_append(0, apseq);
 
2837
        sdp_set_access_protos(&record, aproto);
 
2838
 
 
2839
        features = sdp_data_alloc(SDP_UINT16, &feat);
 
2840
        sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
 
2841
 
 
2842
        sdp_set_info_attr(&record, "AVRCP CT", 0, 0);
 
2843
 
 
2844
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2845
                printf("Service Record registration failed\n");
 
2846
                ret = -1;
 
2847
                goto done;
 
2848
        }
 
2849
 
 
2850
        printf("Remote control service registered\n");
 
2851
 
 
2852
done:
 
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);
 
2857
 
 
2858
        return ret;
 
2859
}
 
2860
 
 
2861
static int add_avrtg(sdp_session_t *session, svc_info_t *si)
 
2862
{
 
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;
 
2870
        int ret = 0;
 
2871
 
 
2872
        memset(&record, 0, sizeof(sdp_record_t));
 
2873
        record.handle = si->handle;
 
2874
 
 
2875
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
2876
        root = sdp_list_append(0, &root_uuid);
 
2877
        sdp_set_browse_groups(&record, root);
 
2878
 
 
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);
 
2882
 
 
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);
 
2887
 
 
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]);
 
2893
 
 
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]);
 
2899
 
 
2900
        aproto = sdp_list_append(0, apseq);
 
2901
        sdp_set_access_protos(&record, aproto);
 
2902
 
 
2903
        features = sdp_data_alloc(SDP_UINT16, &feat);
 
2904
        sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
 
2905
 
 
2906
        sdp_set_info_attr(&record, "AVRCP TG", 0, 0);
 
2907
 
 
2908
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2909
                printf("Service Record registration failed\n");
 
2910
                ret = -1;
 
2911
                goto done;
 
2912
        }
 
2913
 
 
2914
        printf("Remote target service registered\n");
 
2915
 
 
2916
done:
 
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);
 
2921
 
 
2922
        return ret;
 
2923
}
 
2924
 
 
2925
static int add_udi_ue(sdp_session_t *session, svc_info_t *si)
 
2926
{
 
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;
 
2931
 
 
2932
        memset(&record, 0, sizeof(record));
 
2933
        record.handle = si->handle;
 
2934
 
 
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);
 
2939
 
 
2940
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
 
2941
        proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
 
2942
 
 
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)));
 
2946
 
 
2947
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
2948
 
 
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);
 
2953
 
 
2954
        sdp_set_info_attr(&record, "UDI UE", NULL, NULL);
 
2955
 
 
2956
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2957
                printf("Service Record registration failed\n");
 
2958
                return -1;
 
2959
        }
 
2960
 
 
2961
        printf("UDI UE service registered\n");
 
2962
 
 
2963
        return 0;
 
2964
}
 
2965
 
 
2966
static int add_udi_te(sdp_session_t *session, svc_info_t *si)
 
2967
{
 
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;
 
2972
 
 
2973
        memset(&record, 0, sizeof(record));
 
2974
        record.handle = si->handle;
 
2975
 
 
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);
 
2980
 
 
2981
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
 
2982
        proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
 
2983
 
 
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)));
 
2987
 
 
2988
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
2989
 
 
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);
 
2994
 
 
2995
        sdp_set_info_attr(&record, "UDI TE", NULL, NULL);
 
2996
 
 
2997
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
2998
                printf("Service Record registration failed\n");
 
2999
                return -1;
 
3000
        }
 
3001
 
 
3002
        printf("UDI TE service registered\n");
 
3003
 
 
3004
        return 0;
 
3005
}
 
3006
 
 
3007
static unsigned char sr1_uuid[] = {     0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0,
 
3008
                                        0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 };
 
3009
 
 
3010
static int add_sr1(sdp_session_t *session, svc_info_t *si)
 
3011
{
 
3012
        sdp_record_t record;
 
3013
        sdp_list_t *root, *svclass;
 
3014
        uuid_t root_uuid, svclass_uuid;
 
3015
 
 
3016
        memset(&record, 0, sizeof(record));
 
3017
        record.handle = si->handle;
 
3018
 
 
3019
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3020
        root = sdp_list_append(NULL, &root_uuid);
 
3021
        sdp_set_browse_groups(&record, root);
 
3022
 
 
3023
        sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid);
 
3024
        svclass = sdp_list_append(NULL, &svclass_uuid);
 
3025
        sdp_set_service_classes(&record, svclass);
 
3026
 
 
3027
        sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL);
 
3028
 
 
3029
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3030
                printf("Service Record registration failed\n");
 
3031
                return -1;
 
3032
        }
 
3033
 
 
3034
        printf("Toshiba Speech Recognition SR-1 service record registered\n");
 
3035
 
 
3036
        return 0;
 
3037
}
 
3038
 
 
3039
static unsigned char syncmls_uuid[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
 
3040
                                        0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
 
3041
 
 
3042
static unsigned char syncmlc_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
 
3043
                                        0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
 
3044
 
 
3045
static int add_syncml(sdp_session_t *session, svc_info_t *si)
 
3046
{
 
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;
 
3051
 
 
3052
        memset(&record, 0, sizeof(record));
 
3053
        record.handle = si->handle;
 
3054
 
 
3055
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3056
        root = sdp_list_append(NULL, &root_uuid);
 
3057
        sdp_set_browse_groups(&record, root);
 
3058
 
 
3059
        sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid);
 
3060
        svclass = sdp_list_append(NULL, &svclass_uuid);
 
3061
        sdp_set_service_classes(&record, svclass);
 
3062
 
 
3063
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
 
3064
        proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
 
3065
 
 
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)));
 
3069
 
 
3070
        sdp_uuid16_create(&obex_uuid, OBEX_UUID);
 
3071
        proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid));
 
3072
 
 
3073
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
3074
 
 
3075
        sdp_set_info_attr(&record, "SyncML Client", NULL, NULL);
 
3076
 
 
3077
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3078
                printf("Service Record registration failed\n");
 
3079
                return -1;
 
3080
        }
 
3081
 
 
3082
        printf("SyncML Client service record registered\n");
 
3083
 
 
3084
        return 0;
 
3085
}
 
3086
 
 
3087
static unsigned char async_uuid[] = {   0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62,
 
3088
                                        0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C };
 
3089
 
 
3090
static int add_activesync(sdp_session_t *session, svc_info_t *si)
 
3091
{
 
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;
 
3096
 
 
3097
        memset(&record, 0, sizeof(record));
 
3098
        record.handle = si->handle;
 
3099
 
 
3100
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3101
        root = sdp_list_append(NULL, &root_uuid);
 
3102
        sdp_set_browse_groups(&record, root);
 
3103
 
 
3104
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
 
3105
        proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
 
3106
 
 
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)));
 
3110
 
 
3111
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
3112
 
 
3113
        sdp_uuid128_create(&svclass_uuid, (void *) async_uuid);
 
3114
        svclass = sdp_list_append(NULL, &svclass_uuid);
 
3115
        sdp_set_service_classes(&record, svclass);
 
3116
 
 
3117
        sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL);
 
3118
 
 
3119
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3120
                printf("Service Record registration failed\n");
 
3121
                return -1;
 
3122
        }
 
3123
 
 
3124
        printf("ActiveSync service record registered\n");
 
3125
 
 
3126
        return 0;
 
3127
}
 
3128
 
 
3129
static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
 
3130
                                        0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
 
3131
 
 
3132
static int add_hotsync(sdp_session_t *session, svc_info_t *si)
 
3133
{
 
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;
 
3138
 
 
3139
        memset(&record, 0, sizeof(record));
 
3140
        record.handle = si->handle;
 
3141
 
 
3142
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3143
        root = sdp_list_append(NULL, &root_uuid);
 
3144
        sdp_set_browse_groups(&record, root);
 
3145
 
 
3146
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
 
3147
        proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
 
3148
 
 
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)));
 
3152
 
 
3153
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
3154
 
 
3155
        sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
 
3156
        svclass = sdp_list_append(NULL, &svclass_uuid);
 
3157
        sdp_set_service_classes(&record, svclass);
 
3158
 
 
3159
        sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
 
3160
 
 
3161
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3162
                printf("Service Record registration failed\n");
 
3163
                return -1;
 
3164
        }
 
3165
 
 
3166
        printf("HotSync service record registered\n");
 
3167
 
 
3168
        return 0;
 
3169
}
 
3170
 
 
3171
static unsigned char palmos_uuid[] = {  0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51,
 
3172
                                        0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 };
 
3173
 
 
3174
static int add_palmos(sdp_session_t *session, svc_info_t *si)
 
3175
{
 
3176
        sdp_record_t record;
 
3177
        sdp_list_t *root, *svclass;
 
3178
        uuid_t root_uuid, svclass_uuid;
 
3179
 
 
3180
        memset(&record, 0, sizeof(record));
 
3181
        record.handle = si->handle;
 
3182
 
 
3183
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3184
        root = sdp_list_append(NULL, &root_uuid);
 
3185
        sdp_set_browse_groups(&record, root);
 
3186
 
 
3187
        sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid);
 
3188
        svclass = sdp_list_append(NULL, &svclass_uuid);
 
3189
        sdp_set_service_classes(&record, svclass);
 
3190
 
 
3191
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3192
                printf("Service Record registration failed\n");
 
3193
                return -1;
 
3194
        }
 
3195
 
 
3196
        printf("PalmOS service record registered\n");
 
3197
 
 
3198
        return 0;
 
3199
}
 
3200
 
 
3201
static unsigned char nokid_uuid[] = {   0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00,
 
3202
                                        0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
 
3203
 
 
3204
static int add_nokiaid(sdp_session_t *session, svc_info_t *si)
 
3205
{
 
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);
 
3211
 
 
3212
        memset(&record, 0, sizeof(record));
 
3213
        record.handle = si->handle;
 
3214
 
 
3215
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3216
        root = sdp_list_append(NULL, &root_uuid);
 
3217
        sdp_set_browse_groups(&record, root);
 
3218
 
 
3219
        sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid);
 
3220
        svclass = sdp_list_append(NULL, &svclass_uuid);
 
3221
        sdp_set_service_classes(&record, svclass);
 
3222
 
 
3223
        sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version);
 
3224
 
 
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);
 
3228
                return -1;
 
3229
        }
 
3230
 
 
3231
        printf("Nokia ID service record registered\n");
 
3232
 
 
3233
        return 0;
 
3234
}
 
3235
 
 
3236
static unsigned char pcsuite_uuid[] = { 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00,
 
3237
                                        0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
 
3238
 
 
3239
static int add_pcsuite(sdp_session_t *session, svc_info_t *si)
 
3240
{
 
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;
 
3245
 
 
3246
        memset(&record, 0, sizeof(record));
 
3247
        record.handle = si->handle;
 
3248
 
 
3249
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3250
        root = sdp_list_append(NULL, &root_uuid);
 
3251
        sdp_set_browse_groups(&record, root);
 
3252
 
 
3253
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
 
3254
        proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
 
3255
 
 
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)));
 
3259
 
 
3260
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
3261
 
 
3262
        sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid);
 
3263
        svclass = sdp_list_append(NULL, &svclass_uuid);
 
3264
        sdp_set_service_classes(&record, svclass);
 
3265
 
 
3266
        sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL);
 
3267
 
 
3268
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3269
                printf("Service Record registration failed\n");
 
3270
                return -1;
 
3271
        }
 
3272
 
 
3273
        printf("Nokia PC Suite service registered\n");
 
3274
 
 
3275
        return 0;
 
3276
}
 
3277
 
 
3278
static unsigned char nftp_uuid[] = {    0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00,
 
3279
                                        0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
 
3280
 
 
3281
static unsigned char nsyncml_uuid[] = { 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x10, 0x00,
 
3282
                                        0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
 
3283
 
 
3284
static unsigned char ngage_uuid[] = {   0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00,
 
3285
                                        0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
 
3286
 
 
3287
static unsigned char apple_uuid[] = {   0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90,
 
3288
                                        0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 };
 
3289
 
 
3290
static int add_apple(sdp_session_t *session, svc_info_t *si)
 
3291
{
 
3292
        sdp_record_t record;
 
3293
        sdp_list_t *root;
 
3294
        uuid_t root_uuid;
 
3295
        uint32_t attr783 = 0x00000000;
 
3296
        uint32_t attr785 = 0x00000002;
 
3297
        uint16_t attr786 = 0x1234;
 
3298
 
 
3299
        memset(&record, 0, sizeof(record));
 
3300
        record.handle = si->handle;
 
3301
 
 
3302
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3303
        root = sdp_list_append(NULL, &root_uuid);
 
3304
        sdp_set_browse_groups(&record, root);
 
3305
 
 
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);
 
3313
 
 
3314
        sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL);
 
3315
 
 
3316
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3317
                printf("Service Record registration failed\n");
 
3318
                return -1;
 
3319
        }
 
3320
 
 
3321
        printf("Apple attribute service registered\n");
 
3322
 
 
3323
        return 0;
 
3324
}
 
3325
 
 
3326
static int add_isync(sdp_session_t *session, svc_info_t *si)
 
3327
{
 
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;
 
3332
 
 
3333
        memset(&record, 0, sizeof(record));
 
3334
        record.handle = si->handle;
 
3335
 
 
3336
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3337
        root = sdp_list_append(NULL, &root_uuid);
 
3338
        sdp_set_browse_groups(&record, root);
 
3339
 
 
3340
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
 
3341
        proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
 
3342
 
 
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)));
 
3346
 
 
3347
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
3348
 
 
3349
        sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID);
 
3350
        svclass = sdp_list_append(NULL, &serial_uuid);
 
3351
 
 
3352
        sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID);
 
3353
        svclass = sdp_list_append(svclass, &svclass_uuid);
 
3354
 
 
3355
        sdp_set_service_classes(&record, svclass);
 
3356
 
 
3357
        sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd.");
 
3358
 
 
3359
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3360
                printf("Service Record registration failed\n");
 
3361
                return -1;
 
3362
        }
 
3363
 
 
3364
        printf("Apple iSync service registered\n");
 
3365
 
 
3366
        return 0;
 
3367
}
 
3368
 
 
3369
static int add_semchla(sdp_session_t *session, svc_info_t *si)
 
3370
{
 
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;
 
3376
 
 
3377
        memset(&record, 0, sizeof(record));
 
3378
        record.handle = si->handle;
 
3379
 
 
3380
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
 
3381
        root = sdp_list_append(NULL, &root_uuid);
 
3382
        sdp_set_browse_groups(&record, root);
 
3383
 
 
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)));
 
3387
 
 
3388
        sdp_uuid32_create(&semchla_uuid, 0x8e770300);
 
3389
        proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid));
 
3390
 
 
3391
        sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
 
3392
 
 
3393
        sdp_uuid32_create(&service_uuid, 0x8e771301);
 
3394
        svclass = sdp_list_append(NULL, &service_uuid);
 
3395
 
 
3396
        sdp_set_service_classes(&record, svclass);
 
3397
 
 
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);
 
3403
 
 
3404
        sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL);
 
3405
 
 
3406
        if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
 
3407
                printf("Service Record registration failed\n");
 
3408
                return -1;
 
3409
        }
 
3410
 
 
3411
        /* SEMC High Level Authentication */
 
3412
        printf("SEMC HLA service registered\n");
 
3413
 
 
3414
        return 0;
 
3415
}
 
3416
 
 
3417
static int add_gatt(sdp_session_t *session, svc_info_t *si)
 
3418
{
 
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;
 
3425
        int ret;
 
3426
 
 
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);
 
3433
 
 
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);
 
3438
 
 
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);
 
3444
 
 
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]);
 
3450
 
 
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]);
 
3458
 
 
3459
        aproto = sdp_list_append(NULL, apseq);
 
3460
        sdp_set_access_protos(&record, aproto);
 
3461
 
 
3462
        sdp_set_info_attr(&record, "Generic Attribute Profile", "BlueZ", NULL);
 
3463
 
 
3464
        sdp_set_url_attr(&record, "http://www.bluez.org/",
 
3465
                        "http://www.bluez.org/", "http://www.bluez.org/");
 
3466
 
 
3467
        sdp_set_service_id(&record, gatt_uuid);
 
3468
 
 
3469
        ret = sdp_device_record_register(session, &interface, &record,
 
3470
                                                        SDP_RECORD_PERSIST);
 
3471
        if (ret < 0)
 
3472
                printf("Service Record registration failed\n");
 
3473
        else
 
3474
                printf("Generic Attribute Profile Service registered\n");
 
3475
 
 
3476
        sdp_data_free(psm);
 
3477
        sdp_data_free(sh);
 
3478
        sdp_data_free(eh);
 
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);
 
3483
 
 
3484
        return ret;
 
3485
}
 
3486
 
 
3487
struct {
 
3488
        char            *name;
 
3489
        uint32_t        class;
 
3490
        int             (*add)(sdp_session_t *sess, svc_info_t *si);
 
3491
        unsigned char *uuid;
 
3492
} service[] = {
 
3493
        { "DID",        PNP_INFO_SVCLASS_ID,            NULL,           },
 
3494
 
 
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 },
 
3502
 
 
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,       },
 
3509
 
 
3510
        { "NAP",        NAP_SVCLASS_ID,                 add_nap         },
 
3511
        { "GN",         GN_SVCLASS_ID,                  add_gn          },
 
3512
        { "PANU",       PANU_SVCLASS_ID,                add_panu        },
 
3513
 
 
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         },
 
3520
 
 
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       },
 
3525
 
 
3526
        { "UDIUE",      UDI_MT_SVCLASS_ID,              add_udi_ue      },
 
3527
        { "UDITE",      UDI_TA_SVCLASS_ID,              add_udi_te      },
 
3528
 
 
3529
        { "SEMCHLA",    0x8e771301,                     add_semchla     },
 
3530
 
 
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      },
 
3543
 
 
3544
        { "ISYNC",      APPLE_AGENT_SVCLASS_ID,         add_isync,      },
 
3545
        { "GATT",       GENERIC_ATTRIB_SVCLASS_ID,      add_gatt,       },
 
3546
 
 
3547
        { 0 }
 
3548
};
 
3549
 
 
3550
/* Add local service */
 
3551
static int add_service(bdaddr_t *bdaddr, svc_info_t *si)
 
3552
{
 
3553
        sdp_session_t *sess;
 
3554
        int i, ret = -1;
 
3555
 
 
3556
        if (!si->name)
 
3557
                return -1;
 
3558
 
 
3559
        sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
 
3560
        if (!sess)
 
3561
                return -1;
 
3562
 
 
3563
        for (i = 0; service[i].name; i++)
 
3564
                if (!strcasecmp(service[i].name, si->name)) {
 
3565
                        if (service[i].add)
 
3566
                                ret = service[i].add(sess, si);
 
3567
                        goto done;
 
3568
                }
 
3569
 
 
3570
        printf("Unknown service name: %s\n", si->name);
 
3571
 
 
3572
done:
 
3573
        free(si->name);
 
3574
        sdp_close(sess);
 
3575
 
 
3576
        return ret;
 
3577
}
 
3578
 
 
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' },
 
3585
        { 0, 0, 0, 0 }
 
3586
};
 
3587
 
 
3588
static const char *add_help =
 
3589
        "Usage:\n"
 
3590
        "\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n";
 
3591
 
 
3592
static int cmd_add(int argc, char **argv)
 
3593
{
 
3594
        svc_info_t si;
 
3595
        int opt;
 
3596
 
 
3597
        memset(&si, 0, sizeof(si));
 
3598
        si.handle = 0xffffffff;
 
3599
 
 
3600
        for_each_opt(opt, add_options, 0) {
 
3601
                switch (opt) {
 
3602
                case 'r':
 
3603
                        if (strncasecmp(optarg, "0x", 2))
 
3604
                                si.handle = atoi(optarg);
 
3605
                        else
 
3606
                                si.handle = strtol(optarg + 2, NULL, 16);
 
3607
                        break;
 
3608
                case 'p':
 
3609
                        if (strncasecmp(optarg, "0x", 2))
 
3610
                                si.psm = atoi(optarg);
 
3611
                        else
 
3612
                                si.psm = strtol(optarg + 2, NULL, 16);
 
3613
                        break;
 
3614
                case 'c':
 
3615
                        if (strncasecmp(optarg, "0x", 2))
 
3616
                                si.channel = atoi(optarg);
 
3617
                        else
 
3618
                                si.channel = strtol(optarg + 2, NULL, 16);
 
3619
                        break;
 
3620
                case 'n':
 
3621
                        if (strncasecmp(optarg, "0x", 2))
 
3622
                                si.network = atoi(optarg);
 
3623
                        else
 
3624
                                si.network = strtol(optarg + 2, NULL, 16);
 
3625
                        break;
 
3626
                default:
 
3627
                        printf("%s", add_help);
 
3628
                        return -1;
 
3629
                }
 
3630
        }
 
3631
 
 
3632
        argc -= optind;
 
3633
        argv += optind;
 
3634
 
 
3635
        if (argc < 1) {
 
3636
                printf("%s", add_help);
 
3637
                return -1;
 
3638
        }
 
3639
 
 
3640
        si.name = strdup(argv[0]);
 
3641
 
 
3642
        return add_service(0, &si);
 
3643
}
 
3644
 
 
3645
/* Delete local service */
 
3646
static int del_service(bdaddr_t *bdaddr, void *arg)
 
3647
{
 
3648
        uint32_t handle, range = 0x0000ffff;
 
3649
        sdp_list_t *attr;
 
3650
        sdp_session_t *sess;
 
3651
        sdp_record_t *rec;
 
3652
 
 
3653
        if (!arg) {
 
3654
                printf("Record handle was not specified.\n");
 
3655
                return -1;
 
3656
        }
 
3657
 
 
3658
        sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
 
3659
        if (!sess) {
 
3660
                printf("No local SDP server!\n");
 
3661
                return -1;
 
3662
        }
 
3663
 
 
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);
 
3668
 
 
3669
        if (!rec) {
 
3670
                printf("Service Record not found.\n");
 
3671
                sdp_close(sess);
 
3672
                return -1;
 
3673
        }
 
3674
 
 
3675
        if (sdp_device_record_unregister(sess, &interface, rec)) {
 
3676
                printf("Failed to unregister service record: %s\n", strerror(errno));
 
3677
                sdp_close(sess);
 
3678
                return -1;
 
3679
        }
 
3680
 
 
3681
        printf("Service Record deleted.\n");
 
3682
        sdp_close(sess);
 
3683
 
 
3684
        return 0;
 
3685
}
 
3686
 
 
3687
static struct option del_options[] = {
 
3688
        { "help",       0, 0, 'h' },
 
3689
        { 0, 0, 0, 0 }
 
3690
};
 
3691
 
 
3692
static const char *del_help =
 
3693
        "Usage:\n"
 
3694
        "\tdel record_handle\n";
 
3695
 
 
3696
static int cmd_del(int argc, char **argv)
 
3697
{
 
3698
        int opt;
 
3699
 
 
3700
        for_each_opt(opt, del_options, 0) {
 
3701
                switch (opt) {
 
3702
                default:
 
3703
                        printf("%s", del_help);
 
3704
                        return -1;
 
3705
                }
 
3706
        }
 
3707
 
 
3708
        argc -= optind;
 
3709
        argv += optind;
 
3710
 
 
3711
        if (argc < 1) {
 
3712
                printf("%s", del_help);
 
3713
                return -1;
 
3714
        }
 
3715
 
 
3716
        return del_service(NULL, argv[0]);
 
3717
}
 
3718
 
 
3719
/*
 
3720
 * Perform an inquiry and search/browse all peer found.
 
3721
 */
 
3722
static void inquiry(handler_t handler, void *arg)
 
3723
{
 
3724
        inquiry_info ii[20];
 
3725
        uint8_t count = 0;
 
3726
        int i;
 
3727
 
 
3728
        printf("Inquiring ...\n");
 
3729
        if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
 
3730
                printf("Inquiry failed\n");
 
3731
                return;
 
3732
        }
 
3733
 
 
3734
        for (i = 0; i < count; i++)
 
3735
                handler(&ii[i].bdaddr, arg);
 
3736
}
 
3737
 
 
3738
static void doprintf(void *data, const char *str)
 
3739
{
 
3740
        printf("%s", str);
 
3741
}
 
3742
 
 
3743
/*
 
3744
 * Search for a specific SDP service
 
3745
 */
 
3746
static int do_search(bdaddr_t *bdaddr, struct search_context *context)
 
3747
{
 
3748
        sdp_list_t *attrid, *search, *seq, *next;
 
3749
        uint32_t range = 0x0000ffff;
 
3750
        char str[20];
 
3751
        sdp_session_t *sess;
 
3752
 
 
3753
        if (!bdaddr) {
 
3754
                inquiry(do_search, context);
 
3755
                return 0;
 
3756
        }
 
3757
 
 
3758
        sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
 
3759
        ba2str(bdaddr, str);
 
3760
        if (!sess) {
 
3761
                printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
 
3762
                return -1;
 
3763
        }
 
3764
 
 
3765
        if (context->view != RAW_VIEW) {
 
3766
                if (context->svc)
 
3767
                        printf("Searching for %s on %s ...\n", context->svc, str);
 
3768
                else
 
3769
                        printf("Browsing %s ...\n", str);
 
3770
        }
 
3771
 
 
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));
 
3776
                sdp_close(sess);
 
3777
                return -1;
 
3778
        }
 
3779
        sdp_list_free(attrid, 0);
 
3780
        sdp_list_free(search, 0);
 
3781
 
 
3782
        for (; seq; seq = next) {
 
3783
                sdp_record_t *rec = (sdp_record_t *) seq->data;
 
3784
                struct search_context sub_context;
 
3785
 
 
3786
                switch (context->view) {
 
3787
                case DEFAULT_VIEW:
 
3788
                        /* Display user friendly form */
 
3789
                        print_service_attr(rec);
 
3790
                        printf("\n");
 
3791
                        break;
 
3792
                case TREE_VIEW:
 
3793
                        /* Display full tree */
 
3794
                        print_tree_attr(rec);
 
3795
                        printf("\n");
 
3796
                        break;
 
3797
                case XML_VIEW:
 
3798
                        /* Display raw XML tree */
 
3799
                        convert_sdp_record_to_xml(rec, 0, doprintf);
 
3800
                        break;
 
3801
                default:
 
3802
                        /* Display raw tree */
 
3803
                        print_raw_attr(rec);
 
3804
                        break;
 
3805
                }
 
3806
 
 
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);
 
3813
                }
 
3814
                next = seq->next;
 
3815
                free(seq);
 
3816
                sdp_record_free(rec);
 
3817
        }
 
3818
 
 
3819
        sdp_close(sess);
 
3820
        return 0;
 
3821
}
 
3822
 
 
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' },
 
3830
        { 0, 0, 0, 0 }
 
3831
};
 
3832
 
 
3833
static const char *browse_help =
 
3834
        "Usage:\n"
 
3835
        "\tbrowse [--tree] [--raw] [--xml] [--uuid uuid] [--l2cap] [bdaddr]\n";
 
3836
 
 
3837
/*
 
3838
 * Browse the full SDP database (i.e. list all services starting from the
 
3839
 * root/top-level).
 
3840
 */
 
3841
static int cmd_browse(int argc, char **argv)
 
3842
{
 
3843
        struct search_context context;
 
3844
        int opt, num;
 
3845
 
 
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);
 
3850
 
 
3851
        for_each_opt(opt, browse_options, 0) {
 
3852
                switch (opt) {
 
3853
                case 't':
 
3854
                        context.view = TREE_VIEW;
 
3855
                        break;
 
3856
                case 'r':
 
3857
                        context.view = RAW_VIEW;
 
3858
                        break;
 
3859
                case 'x':
 
3860
                        context.view = XML_VIEW;
 
3861
                        break;
 
3862
                case 'u':
 
3863
                        if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) {
 
3864
                                printf("Invalid uuid %s\n", optarg);
 
3865
                                return -1;
 
3866
                        }
 
3867
                        sdp_uuid16_create(&context.group, num);
 
3868
                        break;
 
3869
                case 'l':
 
3870
                        sdp_uuid16_create(&context.group, L2CAP_UUID);
 
3871
                        break;
 
3872
                default:
 
3873
                        printf("%s", browse_help);
 
3874
                        return -1;
 
3875
                }
 
3876
        }
 
3877
 
 
3878
        argc -= optind;
 
3879
        argv += optind;
 
3880
 
 
3881
        if (argc >= 1) {
 
3882
                bdaddr_t bdaddr;
 
3883
                estr2ba(argv[0], &bdaddr);
 
3884
                return do_search(&bdaddr, &context);
 
3885
        }
 
3886
 
 
3887
        return do_search(NULL, &context);
 
3888
}
 
3889
 
 
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' },
 
3896
        { 0, 0, 0, 0}
 
3897
};
 
3898
 
 
3899
static const char *search_help =
 
3900
        "Usage:\n"
 
3901
        "\tsearch [--bdaddr bdaddr] [--tree] [--raw] [--xml] SERVICE\n"
 
3902
        "SERVICE is a name (string) or UUID (0x1002)\n";
 
3903
 
 
3904
/*
 
3905
 * Search for a specific SDP service
 
3906
 *
 
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)
 
3911
 */
 
3912
static int cmd_search(int argc, char **argv)
 
3913
{
 
3914
        struct search_context context;
 
3915
        unsigned char *uuid = NULL;
 
3916
        uint32_t class = 0;
 
3917
        bdaddr_t bdaddr;
 
3918
        int has_addr = 0;
 
3919
        int i;
 
3920
        int opt;
 
3921
 
 
3922
        /* Initialise context */
 
3923
        memset(&context, '\0', sizeof(struct search_context));
 
3924
 
 
3925
        for_each_opt(opt, search_options, 0) {
 
3926
                switch (opt) {
 
3927
                case 'b':
 
3928
                        estr2ba(optarg, &bdaddr);
 
3929
                        has_addr = 1;
 
3930
                        break;
 
3931
                case 't':
 
3932
                        context.view = TREE_VIEW;
 
3933
                        break;
 
3934
                case 'r':
 
3935
                        context.view = RAW_VIEW;
 
3936
                        break;
 
3937
                case 'x':
 
3938
                        context.view = XML_VIEW;
 
3939
                        break;
 
3940
                default:
 
3941
                        printf("%s", search_help);
 
3942
                        return -1;
 
3943
                }
 
3944
        }
 
3945
 
 
3946
        argc -= optind;
 
3947
        argv += optind;
 
3948
 
 
3949
        if (argc < 1) {
 
3950
                printf("%s", search_help);
 
3951
                return -1;
 
3952
        }
 
3953
 
 
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)) {
 
3958
                int num;
 
3959
                /* This is a UUID16, just convert to int */
 
3960
                sscanf(context.svc + 2, "%X", &num);
 
3961
                class = num;
 
3962
                printf("Class 0x%X\n", class);
 
3963
        } else {
 
3964
                /* Convert class name to an UUID */
 
3965
 
 
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;
 
3970
                                break;
 
3971
                        }
 
3972
                if (!class && !uuid) {
 
3973
                        printf("Unknown service %s\n", context.svc);
 
3974
                        return -1;
 
3975
                }
 
3976
        }
 
3977
 
 
3978
        if (class) {
 
3979
                if (class & 0xffff0000)
 
3980
                        sdp_uuid32_create(&context.group, class);
 
3981
                else {
 
3982
                        uint16_t class16 = class & 0xffff;
 
3983
                        sdp_uuid16_create(&context.group, class16);
 
3984
                }
 
3985
        } else
 
3986
                sdp_uuid128_create(&context.group, uuid);
 
3987
 
 
3988
        if (has_addr)
 
3989
                return do_search(&bdaddr, &context);
 
3990
 
 
3991
        return do_search(NULL, &context);
 
3992
}
 
3993
 
 
3994
/*
 
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...
 
3997
 */
 
3998
static int get_service(bdaddr_t *bdaddr, struct search_context *context, int quite)
 
3999
{
 
4000
        sdp_list_t *attrid;
 
4001
        uint32_t range = 0x0000ffff;
 
4002
        sdp_record_t *rec;
 
4003
        sdp_session_t *session = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
 
4004
 
 
4005
        if (!session) {
 
4006
                char str[20];
 
4007
                ba2str(bdaddr, str);
 
4008
                printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
 
4009
                return -1;
 
4010
        }
 
4011
 
 
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);
 
4015
        sdp_close(session);
 
4016
 
 
4017
        if (!rec) {
 
4018
                if (!quite) {
 
4019
                        printf("Service get request failed.\n");
 
4020
                        return -1;
 
4021
                } else
 
4022
                        return 0;
 
4023
        }
 
4024
 
 
4025
        switch (context->view) {
 
4026
        case DEFAULT_VIEW:
 
4027
                /* Display user friendly form */
 
4028
                print_service_attr(rec);
 
4029
                printf("\n");
 
4030
                break;
 
4031
        case TREE_VIEW:
 
4032
                /* Display full tree */
 
4033
                print_tree_attr(rec);
 
4034
                printf("\n");
 
4035
                break;
 
4036
        case XML_VIEW:
 
4037
                /* Display raw XML tree */
 
4038
                convert_sdp_record_to_xml(rec, 0, doprintf);
 
4039
                break;
 
4040
        default:
 
4041
                /* Display raw tree */
 
4042
                print_raw_attr(rec);
 
4043
                break;
 
4044
        }
 
4045
 
 
4046
        sdp_record_free(rec);
 
4047
        return 0;
 
4048
}
 
4049
 
 
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' },
 
4055
        { 0, 0, 0, 0 }
 
4056
};
 
4057
 
 
4058
static const char *records_help =
 
4059
        "Usage:\n"
 
4060
        "\trecords [--tree] [--raw] [--xml] bdaddr\n";
 
4061
 
 
4062
/*
 
4063
 * Request possible SDP service records
 
4064
 */
 
4065
static int cmd_records(int argc, char **argv)
 
4066
{
 
4067
        struct search_context context;
 
4068
        uint32_t base[] = { 0x10000, 0x10300, 0x10500,
 
4069
                                0x1002e, 0x110b, 0x90000, 0x2008000,
 
4070
                                        0x4000000, 0x100000, 0x1000000,
 
4071
                                                0x4f491100, 0x4f491200 };
 
4072
        bdaddr_t bdaddr;
 
4073
        unsigned int i, n, num = 32;
 
4074
        int opt, err = 0;
 
4075
 
 
4076
        /* Initialise context */
 
4077
        memset(&context, '\0', sizeof(struct search_context));
 
4078
 
 
4079
        for_each_opt(opt, records_options, 0) {
 
4080
                switch (opt) {
 
4081
                case 't':
 
4082
                        context.view = TREE_VIEW;
 
4083
                        break;
 
4084
                case 'r':
 
4085
                        context.view = RAW_VIEW;
 
4086
                        break;
 
4087
                case 'x':
 
4088
                        context.view = XML_VIEW;
 
4089
                        break;
 
4090
                default:
 
4091
                        printf("%s", records_help);
 
4092
                        return -1;
 
4093
                }
 
4094
        }
 
4095
 
 
4096
        argc -= optind;
 
4097
        argv += optind;
 
4098
 
 
4099
        if (argc < 1) {
 
4100
                printf("%s", records_help);
 
4101
                return -1;
 
4102
        }
 
4103
 
 
4104
        /* Convert command line parameters */
 
4105
        estr2ba(argv[0], &bdaddr);
 
4106
 
 
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);
 
4111
                        if (err < 0)
 
4112
                                return 0;
 
4113
                }
 
4114
 
 
4115
        return 0;
 
4116
}
 
4117
 
 
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' },
 
4124
        { 0, 0, 0, 0 }
 
4125
};
 
4126
 
 
4127
static const char *get_help =
 
4128
        "Usage:\n"
 
4129
        "\tget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\n";
 
4130
 
 
4131
/*
 
4132
 * Get a specific SDP record on the local SDP server
 
4133
 */
 
4134
static int cmd_get(int argc, char **argv)
 
4135
{
 
4136
        struct search_context context;
 
4137
        bdaddr_t bdaddr;
 
4138
        int has_addr = 0;
 
4139
        int opt;
 
4140
 
 
4141
        /* Initialise context */
 
4142
        memset(&context, '\0', sizeof(struct search_context));
 
4143
 
 
4144
        for_each_opt(opt, get_options, 0) {
 
4145
                switch (opt) {
 
4146
                case 'b':
 
4147
                        estr2ba(optarg, &bdaddr);
 
4148
                        has_addr = 1;
 
4149
                        break;
 
4150
                case 't':
 
4151
                        context.view = TREE_VIEW;
 
4152
                        break;
 
4153
                case 'r':
 
4154
                        context.view = RAW_VIEW;
 
4155
                        break;
 
4156
                case 'x':
 
4157
                        context.view = XML_VIEW;
 
4158
                        break;
 
4159
                default:
 
4160
                        printf("%s", get_help);
 
4161
                        return -1;
 
4162
                }
 
4163
        }
 
4164
 
 
4165
        argc -= optind;
 
4166
        argv += optind;
 
4167
 
 
4168
        if (argc < 1) {
 
4169
                printf("%s", get_help);
 
4170
                return -1;
 
4171
        }
 
4172
 
 
4173
        /* Convert command line parameters */
 
4174
        context.handle = strtoul(argv[0], 0, 16);
 
4175
 
 
4176
        return get_service(has_addr ? &bdaddr : BDADDR_LOCAL, &context, 0);
 
4177
}
 
4178
 
 
4179
static struct {
 
4180
        char *cmd;
 
4181
        int (*func)(int argc, char **argv);
 
4182
        char *doc;
 
4183
} command[] = {
 
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" },
 
4192
        { 0, 0, 0 }
 
4193
};
 
4194
 
 
4195
static void usage(void)
 
4196
{
 
4197
        int i, pos = 0;
 
4198
 
 
4199
        printf("sdptool - SDP tool v%s\n", VERSION);
 
4200
        printf("Usage:\n"
 
4201
                "\tsdptool [options] <command> [command parameters]\n");
 
4202
        printf("Options:\n"
 
4203
                "\t-h\t\tDisplay help\n"
 
4204
                "\t-i\t\tSpecify source interface\n");
 
4205
 
 
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);
 
4209
 
 
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;
 
4214
                if (pos > 60) {
 
4215
                        printf("\n\t");
 
4216
                        pos = 0;
 
4217
                }
 
4218
        }
 
4219
        printf("\n");
 
4220
}
 
4221
 
 
4222
static struct option main_options[] = {
 
4223
        { "help",       0, 0, 'h' },
 
4224
        { "device",     1, 0, 'i' },
 
4225
        { 0, 0, 0, 0 }
 
4226
};
 
4227
 
 
4228
int main(int argc, char *argv[])
 
4229
{
 
4230
        int i, opt;
 
4231
 
 
4232
        bacpy(&interface, BDADDR_ANY);
 
4233
 
 
4234
        while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
 
4235
                switch(opt) {
 
4236
                case 'i':
 
4237
                        if (!strncmp(optarg, "hci", 3))
 
4238
                                hci_devba(atoi(optarg + 3), &interface);
 
4239
                        else
 
4240
                                str2ba(optarg, &interface);
 
4241
                        break;
 
4242
 
 
4243
                case 'h':
 
4244
                        usage();
 
4245
                        exit(0);
 
4246
 
 
4247
                default:
 
4248
                        exit(1);
 
4249
                }
 
4250
        }
 
4251
 
 
4252
        argc -= optind;
 
4253
        argv += optind;
 
4254
        optind = 0;
 
4255
 
 
4256
        if (argc < 1) {
 
4257
                usage();
 
4258
                exit(1);
 
4259
        }
 
4260
 
 
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);
 
4264
 
 
4265
        return 1;
 
4266
}