OSDN Git Service

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