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