OSDN Git Service

Initial Contribution
[android-x86/external-bluetooth-bluez.git] / utils / 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-2008  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 > 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 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(set_help);
832                         return -1;
833                 }
834         }
835
836         argc -= optind;
837         argv += optind;
838
839         if (argc < 3) {
840                 printf(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 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(seq_help);
971                         return -1;
972                 }
973         }
974
975         argc -= optind;
976         argv += optind;
977
978         if (argc < 3) {
979                 printf(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         sdp_data_t *channel, *features;
1619         uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
1620         sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
1621         int ret = 0;
1622
1623         memset(&record, 0, sizeof(sdp_record_t));
1624         record.handle = si->handle;
1625
1626         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1627         root = sdp_list_append(0, &root_uuid);
1628         sdp_set_browse_groups(&record, root);
1629
1630         sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
1631         svclass_id = sdp_list_append(0, &svclass_uuid);
1632         sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
1633         svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1634         sdp_set_service_classes(&record, svclass_id);
1635
1636         sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
1637         profile.version = 0x0105;
1638         pfseq = sdp_list_append(0, &profile);
1639         sdp_set_profile_descs(&record, pfseq);
1640
1641         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1642         proto[0] = sdp_list_append(0, &l2cap_uuid);
1643         apseq = sdp_list_append(0, proto[0]);
1644
1645         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1646         proto[1] = sdp_list_append(0, &rfcomm_uuid);
1647         channel = sdp_data_alloc(SDP_UINT8, &u8);
1648         proto[1] = sdp_list_append(proto[1], channel);
1649         apseq = sdp_list_append(apseq, proto[1]);
1650
1651         features = sdp_data_alloc(SDP_UINT16, &u16);
1652         sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
1653
1654         aproto = sdp_list_append(0, apseq);
1655         sdp_set_access_protos(&record, aproto);
1656
1657         sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
1658
1659         sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
1660
1661         if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
1662                 printf("Service Record registration failed\n");
1663                 ret = -1;
1664                 goto end;
1665         }
1666
1667         printf("Handsfree AG service registered\n");
1668
1669 end:
1670         sdp_data_free(channel);
1671         sdp_list_free(proto[0], 0);
1672         sdp_list_free(proto[1], 0);
1673         sdp_list_free(apseq, 0);
1674         sdp_list_free(aproto, 0);
1675
1676         return ret;
1677 }
1678
1679 static int add_simaccess(sdp_session_t *session, svc_info_t *si)
1680 {
1681         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1682         uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
1683         sdp_profile_desc_t profile;
1684         sdp_list_t *aproto, *proto[2];
1685         sdp_record_t record;
1686         uint8_t u8 = si->channel? si->channel : 8;
1687         uint16_t u16 = 0x31;
1688         sdp_data_t *channel, *features; 
1689         int ret = 0;
1690
1691         memset((void *)&record, 0, sizeof(sdp_record_t));
1692         record.handle = si->handle;
1693
1694         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1695         root = sdp_list_append(0, &root_uuid);
1696         sdp_set_browse_groups(&record, root);
1697
1698         sdp_uuid16_create(&svclass_uuid, SAP_SVCLASS_ID);
1699         svclass_id = sdp_list_append(0, &svclass_uuid);
1700         sdp_uuid16_create(&ga_svclass_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
1701         svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1702         sdp_set_service_classes(&record, svclass_id);
1703
1704         sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID);
1705         profile.version = 0x0101;
1706         pfseq = sdp_list_append(0, &profile);
1707         sdp_set_profile_descs(&record, pfseq);
1708
1709         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1710         proto[0] = sdp_list_append(0, &l2cap_uuid);
1711         apseq = sdp_list_append(0, proto[0]);
1712
1713         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1714         proto[1] = sdp_list_append(0, &rfcomm_uuid);
1715         channel = sdp_data_alloc(SDP_UINT8, &u8);
1716         proto[1] = sdp_list_append(proto[1], channel);
1717         apseq = sdp_list_append(apseq, proto[1]);
1718
1719         features = sdp_data_alloc(SDP_UINT16, &u16);
1720         sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
1721
1722         aproto = sdp_list_append(0, apseq);
1723         sdp_set_access_protos(&record, aproto);
1724
1725         sdp_set_info_attr(&record, "SIM Access", 0, 0);
1726
1727         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1728                 printf("Service Record registration failed\n");
1729                 ret = -1;
1730                 goto end;
1731         }
1732
1733         printf("SIM Access service registered\n");
1734
1735 end:
1736         sdp_data_free(channel);
1737         sdp_list_free(proto[0], 0);
1738         sdp_list_free(proto[1], 0);
1739         sdp_list_free(apseq, 0);
1740         sdp_list_free(aproto, 0);
1741
1742         return ret;
1743 }
1744
1745 static int add_opush(sdp_session_t *session, svc_info_t *si)
1746 {
1747         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1748         uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
1749         sdp_profile_desc_t profile[1];
1750         sdp_list_t *aproto, *proto[3];
1751         sdp_record_t record;
1752         uint8_t chan = si->channel ? si->channel : 9;
1753         sdp_data_t *channel;
1754         uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
1755         //uint8_t formats[] = { 0xff };
1756         void *dtds[sizeof(formats)], *values[sizeof(formats)];
1757         int i;
1758         uint8_t dtd = SDP_UINT8;
1759         sdp_data_t *sflist;
1760         int ret = 0;
1761
1762         memset(&record, 0, sizeof(sdp_record_t));
1763         record.handle = si->handle;
1764
1765         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1766         root = sdp_list_append(0, &root_uuid);
1767         sdp_set_browse_groups(&record, root);
1768
1769         sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
1770         svclass_id = sdp_list_append(0, &opush_uuid);
1771         sdp_set_service_classes(&record, svclass_id);
1772
1773         sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
1774         profile[0].version = 0x0100;
1775         pfseq = sdp_list_append(0, profile);
1776         sdp_set_profile_descs(&record, pfseq);
1777
1778         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1779         proto[0] = sdp_list_append(0, &l2cap_uuid);
1780         apseq = sdp_list_append(0, proto[0]);
1781
1782         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1783         proto[1] = sdp_list_append(0, &rfcomm_uuid);
1784         channel = sdp_data_alloc(SDP_UINT8, &chan);
1785         proto[1] = sdp_list_append(proto[1], channel);
1786         apseq = sdp_list_append(apseq, proto[1]);
1787
1788         sdp_uuid16_create(&obex_uuid, OBEX_UUID);
1789         proto[2] = sdp_list_append(0, &obex_uuid);
1790         apseq = sdp_list_append(apseq, proto[2]);
1791
1792         aproto = sdp_list_append(0, apseq);
1793         sdp_set_access_protos(&record, aproto);
1794
1795         for (i = 0; i < sizeof(formats); i++) {
1796                 dtds[i] = &dtd;
1797                 values[i] = &formats[i];
1798         }
1799         sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
1800         sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
1801
1802         sdp_set_info_attr(&record, "OBEX Object Push", 0, 0);
1803
1804         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1805                 printf("Service Record registration failed\n");
1806                 ret = -1;
1807                 goto end;
1808         }
1809
1810         printf("OBEX Object Push service registered\n");
1811
1812 end:
1813         sdp_data_free(channel);
1814         sdp_list_free(proto[0], 0);
1815         sdp_list_free(proto[1], 0);
1816         sdp_list_free(proto[2], 0);
1817         sdp_list_free(apseq, 0);
1818         sdp_list_free(aproto, 0);
1819
1820         return ret;
1821 }
1822
1823 static int add_ftp(sdp_session_t *session, svc_info_t *si)
1824 {
1825         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1826         uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
1827         sdp_profile_desc_t profile[1];
1828         sdp_list_t *aproto, *proto[3];
1829         sdp_record_t record;
1830         uint8_t u8 = si->channel ? si->channel: 10;
1831         sdp_data_t *channel;
1832         int ret = 0;
1833
1834         memset(&record, 0, sizeof(sdp_record_t));
1835         record.handle = si->handle;
1836
1837         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1838         root = sdp_list_append(0, &root_uuid);
1839         sdp_set_browse_groups(&record, root);
1840
1841         sdp_uuid16_create(&ftrn_uuid, OBEX_FILETRANS_SVCLASS_ID);
1842         svclass_id = sdp_list_append(0, &ftrn_uuid);
1843         sdp_set_service_classes(&record, svclass_id);
1844
1845         sdp_uuid16_create(&profile[0].uuid, OBEX_FILETRANS_PROFILE_ID);
1846         profile[0].version = 0x0100;
1847         pfseq = sdp_list_append(0, &profile[0]);
1848         sdp_set_profile_descs(&record, pfseq);
1849
1850         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1851         proto[0] = sdp_list_append(0, &l2cap_uuid);
1852         apseq = sdp_list_append(0, proto[0]);
1853
1854         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1855         proto[1] = sdp_list_append(0, &rfcomm_uuid);
1856         channel = sdp_data_alloc(SDP_UINT8, &u8);
1857         proto[1] = sdp_list_append(proto[1], channel);
1858         apseq = sdp_list_append(apseq, proto[1]);
1859
1860         sdp_uuid16_create(&obex_uuid, OBEX_UUID);
1861         proto[2] = sdp_list_append(0, &obex_uuid);
1862         apseq = sdp_list_append(apseq, proto[2]);
1863
1864         aproto = sdp_list_append(0, apseq);
1865         sdp_set_access_protos(&record, aproto);
1866
1867         sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0);
1868
1869         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1870                 printf("Service Record registration failed\n");
1871                 ret = -1;
1872                 goto end;
1873         }
1874
1875         printf("OBEX File Transfer service registered\n");
1876
1877 end:
1878         sdp_data_free(channel);
1879         sdp_list_free(proto[0], 0);
1880         sdp_list_free(proto[1], 0);
1881         sdp_list_free(proto[2], 0);
1882         sdp_list_free(apseq, 0);
1883         sdp_list_free(aproto, 0);
1884
1885         return ret;
1886 }
1887
1888 static int add_directprint(sdp_session_t *session, svc_info_t *si)
1889 {
1890         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1891         uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
1892         sdp_profile_desc_t profile[1];
1893         sdp_list_t *aproto, *proto[3];
1894         sdp_record_t record;
1895         uint8_t chan = si->channel ? si->channel : 12;
1896         sdp_data_t *channel;
1897         int ret = 0;
1898
1899         memset(&record, 0, sizeof(sdp_record_t));
1900         record.handle = si->handle;
1901
1902         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1903         root = sdp_list_append(0, &root_uuid);
1904         sdp_set_browse_groups(&record, root);
1905
1906         sdp_uuid16_create(&opush_uuid, DIRECT_PRINTING_SVCLASS_ID);
1907         svclass_id = sdp_list_append(0, &opush_uuid);
1908         sdp_set_service_classes(&record, svclass_id);
1909
1910         sdp_uuid16_create(&profile[0].uuid, BASIC_PRINTING_PROFILE_ID);
1911         profile[0].version = 0x0100;
1912         pfseq = sdp_list_append(0, profile);
1913         sdp_set_profile_descs(&record, pfseq);
1914
1915         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1916         proto[0] = sdp_list_append(0, &l2cap_uuid);
1917         apseq = sdp_list_append(0, proto[0]);
1918
1919         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1920         proto[1] = sdp_list_append(0, &rfcomm_uuid);
1921         channel = sdp_data_alloc(SDP_UINT8, &chan);
1922         proto[1] = sdp_list_append(proto[1], channel);
1923         apseq = sdp_list_append(apseq, proto[1]);
1924
1925         sdp_uuid16_create(&obex_uuid, OBEX_UUID);
1926         proto[2] = sdp_list_append(0, &obex_uuid);
1927         apseq = sdp_list_append(apseq, proto[2]);
1928
1929         aproto = sdp_list_append(0, apseq);
1930         sdp_set_access_protos(&record, aproto);
1931
1932         sdp_set_info_attr(&record, "Direct Printing", 0, 0);
1933
1934         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
1935                 printf("Service Record registration failed\n");
1936                 ret = -1;
1937                 goto end;
1938         }
1939
1940         printf("Direct Printing service registered\n");
1941
1942 end:
1943         sdp_data_free(channel);
1944         sdp_list_free(proto[0], 0);
1945         sdp_list_free(proto[1], 0);
1946         sdp_list_free(proto[2], 0);
1947         sdp_list_free(apseq, 0);
1948         sdp_list_free(aproto, 0);
1949
1950         return ret;
1951 }
1952
1953 static int add_nap(sdp_session_t *session, svc_info_t *si)
1954 {
1955         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1956         uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
1957         sdp_profile_desc_t profile[1];
1958         sdp_list_t *aproto, *proto[2];
1959         sdp_record_t record;
1960         uint16_t lp = 0x000f, ver = 0x0100;
1961         sdp_data_t *psm, *version;
1962         int ret = 0;
1963
1964         memset(&record, 0, sizeof(sdp_record_t));
1965         record.handle = si->handle;
1966
1967         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1968         root = sdp_list_append(0, &root_uuid);
1969         sdp_set_browse_groups(&record, root);
1970
1971         sdp_uuid16_create(&ftrn_uuid, NAP_SVCLASS_ID);
1972         svclass_id = sdp_list_append(0, &ftrn_uuid);
1973         sdp_set_service_classes(&record, svclass_id);
1974
1975         sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
1976         profile[0].version = 0x0100;
1977         pfseq = sdp_list_append(0, &profile[0]);
1978         sdp_set_profile_descs(&record, pfseq);
1979
1980         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1981         proto[0] = sdp_list_append(0, &l2cap_uuid);
1982         psm = sdp_data_alloc(SDP_UINT16, &lp);
1983         proto[0] = sdp_list_append(proto[0], psm);
1984         apseq = sdp_list_append(0, proto[0]);
1985
1986         sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
1987         proto[1] = sdp_list_append(0, &bnep_uuid);
1988         version  = sdp_data_alloc(SDP_UINT16, &ver);
1989         proto[1] = sdp_list_append(proto[1], version);
1990
1991         {
1992                 uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 };
1993                 sdp_data_t *head, *pseq;
1994                 int p;
1995
1996                 for (p = 0, head = NULL; p < 4; p++) {
1997                         sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
1998                         head = sdp_seq_append(head, data);
1999                 }
2000                 pseq = sdp_data_alloc(SDP_SEQ16, head);
2001                 proto[1] = sdp_list_append(proto[1], pseq);
2002         }
2003
2004         apseq = sdp_list_append(apseq, proto[1]);
2005
2006         aproto = sdp_list_append(0, apseq);
2007         sdp_set_access_protos(&record, aproto);
2008
2009         sdp_set_info_attr(&record, "Network Access Point Service", 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("NAP service registered\n");
2018
2019 end:
2020         sdp_data_free(version);
2021         sdp_data_free(psm);
2022         sdp_list_free(proto[0], 0);
2023         sdp_list_free(proto[1], 0);
2024         sdp_list_free(apseq, 0);
2025         sdp_list_free(aproto, 0);
2026
2027         return ret;
2028 }
2029
2030 static int add_gn(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, GN_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, GN_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         apseq = sdp_list_append(apseq, proto[1]);
2068
2069         aproto = sdp_list_append(0, apseq);
2070         sdp_set_access_protos(&record, aproto);
2071
2072         sdp_set_info_attr(&record, "Group Network Service", 0, 0);
2073
2074         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2075                 printf("Service Record registration failed\n");
2076                 ret = -1;
2077                 goto end;
2078         }
2079
2080         printf("GN service registered\n");
2081
2082 end:
2083         sdp_data_free(version);
2084         sdp_data_free(psm);
2085         sdp_list_free(proto[0], 0);
2086         sdp_list_free(proto[1], 0);
2087         sdp_list_free(apseq, 0);
2088         sdp_list_free(aproto, 0);
2089
2090         return ret;
2091 }
2092
2093 static int add_panu(sdp_session_t *session, svc_info_t *si)
2094 {
2095         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2096         uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
2097         sdp_profile_desc_t profile[1];
2098         sdp_list_t *aproto, *proto[2];
2099         sdp_record_t record;
2100         uint16_t lp = 0x000f, ver = 0x0100;
2101         sdp_data_t *psm, *version;
2102         int ret = 0;
2103
2104         memset(&record, 0, sizeof(sdp_record_t));
2105         record.handle = si->handle;
2106
2107         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2108         root = sdp_list_append(NULL, &root_uuid);
2109         sdp_set_browse_groups(&record, root);
2110         sdp_list_free(root, NULL);
2111
2112         sdp_uuid16_create(&ftrn_uuid, PANU_SVCLASS_ID);
2113         svclass_id = sdp_list_append(NULL, &ftrn_uuid);
2114         sdp_set_service_classes(&record, svclass_id);
2115         sdp_list_free(svclass_id, NULL);
2116
2117         sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
2118         profile[0].version = 0x0100;
2119         pfseq = sdp_list_append(NULL, &profile[0]);
2120         sdp_set_profile_descs(&record, pfseq);
2121         sdp_list_free(pfseq, NULL);
2122
2123         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2124         proto[0] = sdp_list_append(NULL, &l2cap_uuid);
2125         psm = sdp_data_alloc(SDP_UINT16, &lp);
2126         proto[0] = sdp_list_append(proto[0], psm);
2127         apseq = sdp_list_append(NULL, proto[0]);
2128
2129         sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
2130         proto[1] = sdp_list_append(NULL, &bnep_uuid);
2131         version = sdp_data_alloc(SDP_UINT16, &ver);
2132         proto[1] = sdp_list_append(proto[1], version);
2133         apseq = sdp_list_append(apseq, proto[1]);
2134
2135         aproto = sdp_list_append(NULL, apseq);
2136         sdp_set_access_protos(&record, aproto);
2137
2138         sdp_set_info_attr(&record, "PAN User", NULL, NULL);
2139
2140         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2141                 printf("Service Record registration failed\n");
2142                 ret = -1;
2143                 goto end;
2144         }
2145
2146         printf("PANU service registered\n");
2147
2148 end:
2149         sdp_data_free(version);
2150         sdp_data_free(psm);
2151         sdp_list_free(proto[0], 0);
2152         sdp_list_free(proto[1], 0);
2153         sdp_list_free(apseq, 0);
2154         sdp_list_free(aproto, 0);
2155
2156         return ret;
2157 }
2158
2159 static int add_hid_keyb(sdp_session_t *session, svc_info_t *si)
2160 {
2161         sdp_record_t record;
2162         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2163         uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid;
2164         sdp_profile_desc_t profile[1];
2165         sdp_list_t *aproto, *proto[3];
2166         sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
2167         int i;
2168         uint8_t dtd = SDP_UINT16;
2169         uint8_t dtd2 = SDP_UINT8;
2170         uint8_t dtd_data = SDP_TEXT_STR8;
2171         void *dtds[2];
2172         void *values[2];
2173         void *dtds2[2];
2174         void *values2[2];
2175         int leng[2];
2176         uint8_t hid_spec_type = 0x22;
2177         uint16_t hid_attr_lang[] = { 0x409, 0x100 };
2178         static const uint16_t ctrl = 0x11;
2179         static const uint16_t intr = 0x13;
2180         static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 };
2181         static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 };
2182         const uint8_t hid_spec[] = { 
2183                 0x05, 0x01, // usage page
2184                 0x09, 0x06, // keyboard
2185                 0xa1, 0x01, // key codes
2186                 0x85, 0x01, // minimum
2187                 0x05, 0x07, // max
2188                 0x19, 0xe0, // logical min
2189                 0x29, 0xe7, // logical max
2190                 0x15, 0x00, // report size
2191                 0x25, 0x01, // report count
2192                 0x75, 0x01, // input data variable absolute
2193                 0x95, 0x08, // report count
2194                 0x81, 0x02, // report size
2195                 0x75, 0x08, 
2196                 0x95, 0x01, 
2197                 0x81, 0x01, 
2198                 0x75, 0x01, 
2199                 0x95, 0x05,
2200                 0x05, 0x08,
2201                 0x19, 0x01,
2202                 0x29, 0x05, 
2203                 0x91, 0x02,
2204                 0x75, 0x03,
2205                 0x95, 0x01,
2206                 0x91, 0x01,
2207                 0x75, 0x08,
2208                 0x95, 0x06,
2209                 0x15, 0x00,
2210                 0x26, 0xff,
2211                 0x00, 0x05,
2212                 0x07, 0x19,
2213                 0x00, 0x2a,
2214                 0xff, 0x00,
2215                 0x81, 0x00,
2216                 0x75, 0x01,
2217                 0x95, 0x01,
2218                 0x15, 0x00,
2219                 0x25, 0x01,
2220                 0x05, 0x0c,
2221                 0x09, 0xb8,
2222                 0x81, 0x06,
2223                 0x09, 0xe2,
2224                 0x81, 0x06,
2225                 0x09, 0xe9,
2226                 0x81, 0x02,
2227                 0x09, 0xea,
2228                 0x81, 0x02,
2229                 0x75, 0x01,
2230                 0x95, 0x04,
2231                 0x81, 0x01,
2232                 0xc0         // end tag
2233         };
2234
2235         memset(&record, 0, sizeof(sdp_record_t));
2236         record.handle = si->handle;
2237
2238         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2239         root = sdp_list_append(0, &root_uuid);
2240         sdp_set_browse_groups(&record, root);
2241
2242         add_lang_attr(&record);
2243
2244         sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
2245         svclass_id = sdp_list_append(0, &hidkb_uuid);
2246         sdp_set_service_classes(&record, svclass_id);
2247
2248         sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
2249         profile[0].version = 0x0100;
2250         pfseq = sdp_list_append(0, profile);
2251         sdp_set_profile_descs(&record, pfseq);
2252
2253         /* protocols */
2254         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2255         proto[1] = sdp_list_append(0, &l2cap_uuid);
2256         psm = sdp_data_alloc(SDP_UINT16, &ctrl);
2257         proto[1] = sdp_list_append(proto[1], psm);
2258         apseq = sdp_list_append(0, proto[1]);
2259
2260         sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2261         proto[2] = sdp_list_append(0, &hidp_uuid);
2262         apseq = sdp_list_append(apseq, proto[2]);
2263
2264         aproto = sdp_list_append(0, apseq);
2265         sdp_set_access_protos(&record, aproto);
2266
2267         /* additional protocols */
2268         proto[1] = sdp_list_append(0, &l2cap_uuid);
2269         psm = sdp_data_alloc(SDP_UINT16, &intr);
2270         proto[1] = sdp_list_append(proto[1], psm);
2271         apseq = sdp_list_append(0, proto[1]);
2272
2273         sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2274         proto[2] = sdp_list_append(0, &hidp_uuid);
2275         apseq = sdp_list_append(apseq, proto[2]);
2276
2277         aproto = sdp_list_append(0, apseq);
2278         sdp_set_add_access_protos(&record, aproto);
2279
2280         sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL);
2281
2282         for (i = 0; i < sizeof(hid_attr) / 2; i++)
2283                 sdp_attr_add_new(&record,
2284                                         SDP_ATTR_HID_DEVICE_RELEASE_NUMBER + i,
2285                                         SDP_UINT16, &hid_attr[i]);
2286
2287         dtds[0] = &dtd2;
2288         values[0] = &hid_spec_type;
2289         dtds[1] = &dtd_data;
2290         values[1] = (uint8_t *) hid_spec;
2291         leng[0] = 0;
2292         leng[1] = sizeof(hid_spec);
2293         hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
2294         hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
2295         sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
2296
2297         for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
2298                 dtds2[i] = &dtd;
2299                 values2[i] = &hid_attr_lang[i];
2300         }
2301
2302         lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
2303         lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
2304         sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
2305
2306         sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]);
2307
2308         for (i = 0; i < sizeof(hid_attr2) / 2 - 1; i++)
2309                 sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP + i,
2310                                                 SDP_UINT16, &hid_attr2[i + 1]);
2311
2312         if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
2313                 printf("Service Record registration failed\n");
2314                 return -1;
2315         }
2316
2317         printf("HID keyboard service registered\n");
2318
2319         return 0;
2320 }
2321
2322 static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si)
2323 {
2324         sdp_record_t record;
2325         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2326         uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid;
2327         sdp_profile_desc_t profile[1];
2328         sdp_list_t *aproto, *proto[3];
2329         sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
2330         int i;
2331         uint8_t dtd = SDP_UINT16;
2332         uint8_t dtd2 = SDP_UINT8;
2333         uint8_t dtd_data = SDP_TEXT_STR8;
2334         void *dtds[2];
2335         void *values[2];
2336         void *dtds2[2];
2337         void *values2[2];
2338         int leng[2];
2339         uint8_t hid_spec_type = 0x22;
2340         uint16_t hid_attr_lang[] = { 0x409, 0x100 };
2341         uint16_t ctrl = 0x11, intr = 0x13;
2342         uint16_t hid_release = 0x0100, parser_version = 0x0111;
2343         uint8_t subclass = 0x04, country = 0x33;
2344         uint8_t virtual_cable = 0, reconnect = 1, sdp_disable = 0;
2345         uint8_t battery = 1, remote_wakeup = 1;
2346         uint16_t profile_version = 0x0100, superv_timeout = 0x0c80;
2347         uint8_t norm_connect = 0, boot_device = 0;
2348         const uint8_t hid_spec[] = {
2349                 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10,
2350                 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
2351                 0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00,
2352                 0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2353                 0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00,
2354                 0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2355                 0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2356                 0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2357                 0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
2358                 0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00,
2359                 0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
2360                 0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2361                 0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
2362                 0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00,
2363                 0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2364                 0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00,
2365                 0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00,
2366                 0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00,
2367                 0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00,
2368                 0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00,
2369                 0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2370                 0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2371                 0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2372                 0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2373                 0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2374                 0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2375                 0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
2376                 0xc0, 0x00
2377         };
2378
2379         memset(&record, 0, sizeof(sdp_record_t));
2380         record.handle = si->handle;
2381
2382         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2383         root = sdp_list_append(NULL, &root_uuid);
2384         sdp_set_browse_groups(&record, root);
2385
2386         sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID);
2387         svclass_id = sdp_list_append(NULL, &hid_uuid);
2388         sdp_set_service_classes(&record, svclass_id);
2389
2390         sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
2391         profile[0].version = 0x0100;
2392         pfseq = sdp_list_append(NULL, profile);
2393         sdp_set_profile_descs(&record, pfseq);
2394
2395         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2396         proto[1] = sdp_list_append(0, &l2cap_uuid);
2397         psm = sdp_data_alloc(SDP_UINT16, &ctrl);
2398         proto[1] = sdp_list_append(proto[1], psm);
2399         apseq = sdp_list_append(0, proto[1]);
2400
2401         sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2402         proto[2] = sdp_list_append(0, &hidp_uuid);
2403         apseq = sdp_list_append(apseq, proto[2]);
2404
2405         aproto = sdp_list_append(0, apseq);
2406         sdp_set_access_protos(&record, aproto);
2407
2408         proto[1] = sdp_list_append(0, &l2cap_uuid);
2409         psm = sdp_data_alloc(SDP_UINT16, &intr);
2410         proto[1] = sdp_list_append(proto[1], psm);
2411         apseq = sdp_list_append(0, proto[1]);
2412
2413         sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
2414         proto[2] = sdp_list_append(0, &hidp_uuid);
2415         apseq = sdp_list_append(apseq, proto[2]);
2416
2417         aproto = sdp_list_append(0, apseq);
2418         sdp_set_add_access_protos(&record, aproto);
2419
2420         add_lang_attr(&record);
2421
2422         sdp_set_info_attr(&record, "Nintendo RVL-CNT-01",
2423                                         "Nintendo", "Nintendo RVL-CNT-01");
2424
2425         sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
2426                                                 SDP_UINT16, &hid_release);
2427
2428         sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION,
2429                                                 SDP_UINT16, &parser_version);
2430
2431         sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS,
2432                                                 SDP_UINT8, &subclass);
2433
2434         sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE,
2435                                                 SDP_UINT8, &country);
2436
2437         sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE,
2438                                                 SDP_BOOL, &virtual_cable);
2439
2440         sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE,
2441                                                 SDP_BOOL, &reconnect);
2442
2443         dtds[0] = &dtd2;
2444         values[0] = &hid_spec_type;
2445         dtds[1] = &dtd_data;
2446         values[1] = (uint8_t *) hid_spec;
2447         leng[0] = 0;
2448         leng[1] = sizeof(hid_spec);
2449         hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
2450         hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
2451         sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
2452
2453         for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
2454                 dtds2[i] = &dtd;
2455                 values2[i] = &hid_attr_lang[i];
2456         }
2457
2458         lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
2459         lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
2460         sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
2461
2462         sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE,
2463                                                 SDP_BOOL, &sdp_disable);
2464
2465         sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER,
2466                                                 SDP_BOOL, &battery);
2467
2468         sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP,
2469                                                 SDP_BOOL, &remote_wakeup);
2470
2471         sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION,
2472                                                 SDP_UINT16, &profile_version);
2473
2474         sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT,
2475                                                 SDP_UINT16, &superv_timeout);
2476
2477         sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE,
2478                                                 SDP_BOOL, &norm_connect);
2479
2480         sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE,
2481                                                 SDP_BOOL, &boot_device);
2482
2483         if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
2484                 printf("Service Record registration failed\n");
2485                 return -1;
2486         }
2487
2488         printf("Wii-Mote service registered\n");
2489
2490         return 0;
2491 }
2492
2493 static int add_cip(sdp_session_t *session, svc_info_t *si)
2494 {
2495         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2496         uuid_t root_uuid, l2cap, cmtp, cip;
2497         sdp_profile_desc_t profile[1];
2498         sdp_list_t *aproto, *proto[2];
2499         sdp_record_t record;
2500         uint16_t psm = si->psm ? si->psm : 0x1001;
2501         uint8_t netid = si->network ? si->network : 0x02; // 0x02 = ISDN, 0x03 = GSM
2502         sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
2503         int ret = 0;
2504
2505         memset(&record, 0, sizeof(sdp_record_t));
2506         record.handle = si->handle;
2507
2508         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2509         root = sdp_list_append(0, &root_uuid);
2510         sdp_set_browse_groups(&record, root);
2511
2512         sdp_uuid16_create(&cip, CIP_SVCLASS_ID);
2513         svclass_id = sdp_list_append(0, &cip);
2514         sdp_set_service_classes(&record, svclass_id);
2515
2516         sdp_uuid16_create(&profile[0].uuid, CIP_PROFILE_ID);
2517         profile[0].version = 0x0100;
2518         pfseq = sdp_list_append(0, &profile[0]);
2519         sdp_set_profile_descs(&record, pfseq);
2520
2521         sdp_uuid16_create(&l2cap, L2CAP_UUID);
2522         proto[0] = sdp_list_append(0, &l2cap);
2523         apseq = sdp_list_append(0, proto[0]);
2524         proto[0] = sdp_list_append(proto[0], sdp_data_alloc(SDP_UINT16, &psm));
2525         apseq = sdp_list_append(0, proto[0]);
2526
2527         sdp_uuid16_create(&cmtp, CMTP_UUID);
2528         proto[1] = sdp_list_append(0, &cmtp);
2529         apseq = sdp_list_append(apseq, proto[1]);
2530
2531         aproto = sdp_list_append(0, apseq);
2532         sdp_set_access_protos(&record, aproto);
2533
2534         sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
2535
2536         sdp_set_info_attr(&record, "Common ISDN Access", 0, 0);
2537
2538         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2539                 printf("Service Record registration failed\n");
2540                 ret = -1;
2541                 goto end;
2542         }
2543
2544         printf("CIP service registered\n");
2545
2546 end:
2547         sdp_list_free(proto[0], 0);
2548         sdp_list_free(proto[1], 0);
2549         sdp_list_free(apseq, 0);
2550         sdp_list_free(aproto, 0);
2551         sdp_data_free(network);
2552
2553         return ret;
2554 }
2555
2556 static int add_ctp(sdp_session_t *session, svc_info_t *si)
2557 {
2558         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2559         uuid_t root_uuid, l2cap, tcsbin, ctp;
2560         sdp_profile_desc_t profile[1];
2561         sdp_list_t *aproto, *proto[2];
2562         sdp_record_t record;
2563         uint8_t netid = si->network ? si->network : 0x02; // 0x01-0x07 cf. p120 profile document
2564         sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
2565         int ret = 0;
2566
2567         memset(&record, 0, sizeof(sdp_record_t));
2568         record.handle = si->handle;
2569
2570         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2571         root = sdp_list_append(0, &root_uuid);
2572         sdp_set_browse_groups(&record, root);
2573
2574         sdp_uuid16_create(&ctp, CORDLESS_TELEPHONY_SVCLASS_ID);
2575         svclass_id = sdp_list_append(0, &ctp);
2576         sdp_set_service_classes(&record, svclass_id);
2577
2578         sdp_uuid16_create(&profile[0].uuid, CORDLESS_TELEPHONY_PROFILE_ID);
2579         profile[0].version = 0x0100;
2580         pfseq = sdp_list_append(0, &profile[0]);
2581         sdp_set_profile_descs(&record, pfseq);
2582
2583         sdp_uuid16_create(&l2cap, L2CAP_UUID);
2584         proto[0] = sdp_list_append(0, &l2cap);
2585         apseq = sdp_list_append(0, proto[0]);
2586
2587         sdp_uuid16_create(&tcsbin, TCS_BIN_UUID);
2588         proto[1] = sdp_list_append(0, &tcsbin);
2589         apseq = sdp_list_append(apseq, proto[1]);
2590
2591         aproto = sdp_list_append(0, apseq);
2592         sdp_set_access_protos(&record, aproto);
2593
2594         sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
2595
2596         sdp_set_info_attr(&record, "Cordless Telephony", 0, 0);
2597
2598         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2599                 printf("Service Record registration failed\n");
2600                 ret = -1;
2601                 goto end;
2602         }
2603
2604         printf("CTP service registered\n");
2605
2606 end:
2607         sdp_list_free(proto[0], 0);
2608         sdp_list_free(proto[1], 0);
2609         sdp_list_free(apseq, 0);
2610         sdp_list_free(aproto, 0);
2611         sdp_data_free(network);
2612
2613         return ret;
2614 }
2615
2616 static int add_a2source(sdp_session_t *session, svc_info_t *si)
2617 {
2618         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2619         uuid_t root_uuid, l2cap, avdtp, a2src;
2620         sdp_profile_desc_t profile[1];
2621         sdp_list_t *aproto, *proto[2];
2622         sdp_record_t record;
2623         sdp_data_t *psm, *version;
2624         uint16_t lp = 0x0019, ver = 0x0100;
2625         int ret = 0;
2626
2627         memset(&record, 0, sizeof(sdp_record_t));
2628         record.handle = si->handle;
2629
2630         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2631         root = sdp_list_append(0, &root_uuid);
2632         sdp_set_browse_groups(&record, root);
2633
2634         sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
2635         svclass_id = sdp_list_append(0, &a2src);
2636         sdp_set_service_classes(&record, svclass_id);
2637
2638         sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
2639         profile[0].version = 0x0100;
2640         pfseq = sdp_list_append(0, &profile[0]);
2641         sdp_set_profile_descs(&record, pfseq);
2642
2643         sdp_uuid16_create(&l2cap, L2CAP_UUID);
2644         proto[0] = sdp_list_append(0, &l2cap);
2645         psm = sdp_data_alloc(SDP_UINT16, &lp);
2646         proto[0] = sdp_list_append(proto[0], psm);
2647         apseq = sdp_list_append(0, proto[0]);
2648
2649         sdp_uuid16_create(&avdtp, AVDTP_UUID);
2650         proto[1] = sdp_list_append(0, &avdtp);
2651         version = sdp_data_alloc(SDP_UINT16, &ver);
2652         proto[1] = sdp_list_append(proto[1], version);
2653         apseq = sdp_list_append(apseq, proto[1]);
2654
2655         aproto = sdp_list_append(0, apseq);
2656         sdp_set_access_protos(&record, aproto);
2657
2658         sdp_set_info_attr(&record, "Audio Source", 0, 0);
2659
2660         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2661                 printf("Service Record registration failed\n");
2662                 ret = -1;
2663                 goto done;
2664         }
2665
2666         printf("Audio source service registered\n");
2667
2668 done:
2669         sdp_list_free(proto[0], 0);
2670         sdp_list_free(proto[1], 0);
2671         sdp_list_free(apseq, 0);
2672         sdp_list_free(aproto, 0);
2673
2674         return ret;
2675 }
2676
2677 static int add_a2sink(sdp_session_t *session, svc_info_t *si)
2678 {
2679         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2680         uuid_t root_uuid, l2cap, avdtp, a2snk;
2681         sdp_profile_desc_t profile[1];
2682         sdp_list_t *aproto, *proto[2];
2683         sdp_record_t record;
2684         sdp_data_t *psm, *version;
2685         uint16_t lp = 0x0019, ver = 0x0100;
2686         int ret = 0;
2687
2688         memset(&record, 0, sizeof(sdp_record_t));
2689         record.handle = si->handle;
2690
2691         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2692         root = sdp_list_append(0, &root_uuid);
2693         sdp_set_browse_groups(&record, root);
2694
2695         sdp_uuid16_create(&a2snk, AUDIO_SINK_SVCLASS_ID);
2696         svclass_id = sdp_list_append(0, &a2snk);
2697         sdp_set_service_classes(&record, svclass_id);
2698
2699         sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
2700         profile[0].version = 0x0100;
2701         pfseq = sdp_list_append(0, &profile[0]);
2702         sdp_set_profile_descs(&record, pfseq);
2703
2704         sdp_uuid16_create(&l2cap, L2CAP_UUID);
2705         proto[0] = sdp_list_append(0, &l2cap);
2706         psm = sdp_data_alloc(SDP_UINT16, &lp);
2707         proto[0] = sdp_list_append(proto[0], psm);
2708         apseq = sdp_list_append(0, proto[0]);
2709
2710         sdp_uuid16_create(&avdtp, AVDTP_UUID);
2711         proto[1] = sdp_list_append(0, &avdtp);
2712         version = sdp_data_alloc(SDP_UINT16, &ver);
2713         proto[1] = sdp_list_append(proto[1], version);
2714         apseq = sdp_list_append(apseq, proto[1]);
2715
2716         aproto = sdp_list_append(0, apseq);
2717         sdp_set_access_protos(&record, aproto);
2718
2719         sdp_set_info_attr(&record, "Audio Sink", 0, 0);
2720
2721         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2722                 printf("Service Record registration failed\n");
2723                 ret = -1;
2724                 goto done;
2725         }
2726
2727         printf("Audio sink service registered\n");
2728
2729 done:
2730         sdp_list_free(proto[0], 0);
2731         sdp_list_free(proto[1], 0);
2732         sdp_list_free(apseq, 0);
2733         sdp_list_free(aproto, 0);
2734
2735         return ret;
2736 }
2737
2738 static int add_avrct(sdp_session_t *session, svc_info_t *si)
2739 {
2740         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2741         uuid_t root_uuid, l2cap, avctp, avrct;
2742         sdp_profile_desc_t profile[1];
2743         sdp_list_t *aproto, *proto[2];
2744         sdp_record_t record;
2745         sdp_data_t *psm, *version, *features;
2746         uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
2747         int ret = 0;
2748
2749         memset(&record, 0, sizeof(sdp_record_t));
2750         record.handle = si->handle;
2751
2752         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2753         root = sdp_list_append(0, &root_uuid);
2754         sdp_set_browse_groups(&record, root);
2755
2756         sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);
2757         svclass_id = sdp_list_append(0, &avrct);
2758         sdp_set_service_classes(&record, svclass_id);
2759
2760         sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
2761         profile[0].version = 0x0100;
2762         pfseq = sdp_list_append(0, &profile[0]);
2763         sdp_set_profile_descs(&record, pfseq);
2764
2765         sdp_uuid16_create(&l2cap, L2CAP_UUID);
2766         proto[0] = sdp_list_append(0, &l2cap);
2767         psm = sdp_data_alloc(SDP_UINT16, &lp);
2768         proto[0] = sdp_list_append(proto[0], psm);
2769         apseq = sdp_list_append(0, proto[0]);
2770
2771         sdp_uuid16_create(&avctp, AVCTP_UUID);
2772         proto[1] = sdp_list_append(0, &avctp);
2773         version = sdp_data_alloc(SDP_UINT16, &ver);
2774         proto[1] = sdp_list_append(proto[1], version);
2775         apseq = sdp_list_append(apseq, proto[1]);
2776
2777         aproto = sdp_list_append(0, apseq);
2778         sdp_set_access_protos(&record, aproto);
2779
2780         features = sdp_data_alloc(SDP_UINT16, &feat);
2781         sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
2782
2783         sdp_set_info_attr(&record, "AVRCP CT", 0, 0);
2784
2785         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2786                 printf("Service Record registration failed\n");
2787                 ret = -1;
2788                 goto done;
2789         }
2790
2791         printf("Remote control service registered\n");
2792
2793 done:
2794         sdp_list_free(proto[0], 0);
2795         sdp_list_free(proto[1], 0);
2796         sdp_list_free(apseq, 0);
2797         sdp_list_free(aproto, 0);
2798
2799         return ret;
2800 }
2801
2802 static int add_avrtg(sdp_session_t *session, svc_info_t *si)
2803 {
2804         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
2805         uuid_t root_uuid, l2cap, avctp, avrtg;
2806         sdp_profile_desc_t profile[1];
2807         sdp_list_t *aproto, *proto[2];
2808         sdp_record_t record;
2809         sdp_data_t *psm, *version, *features;
2810         uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
2811         int ret = 0;
2812
2813         memset(&record, 0, sizeof(sdp_record_t));
2814         record.handle = si->handle;
2815
2816         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2817         root = sdp_list_append(0, &root_uuid);
2818         sdp_set_browse_groups(&record, root);
2819
2820         sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
2821         svclass_id = sdp_list_append(0, &avrtg);
2822         sdp_set_service_classes(&record, svclass_id);
2823
2824         sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
2825         profile[0].version = 0x0100;
2826         pfseq = sdp_list_append(0, &profile[0]);
2827         sdp_set_profile_descs(&record, pfseq);
2828
2829         sdp_uuid16_create(&l2cap, L2CAP_UUID);
2830         proto[0] = sdp_list_append(0, &l2cap);
2831         psm = sdp_data_alloc(SDP_UINT16, &lp);
2832         proto[0] = sdp_list_append(proto[0], psm);
2833         apseq = sdp_list_append(0, proto[0]);
2834
2835         sdp_uuid16_create(&avctp, AVCTP_UUID);
2836         proto[1] = sdp_list_append(0, &avctp);
2837         version = sdp_data_alloc(SDP_UINT16, &ver);
2838         proto[1] = sdp_list_append(proto[1], version);
2839         apseq = sdp_list_append(apseq, proto[1]);
2840
2841         aproto = sdp_list_append(0, apseq);
2842         sdp_set_access_protos(&record, aproto);
2843
2844         features = sdp_data_alloc(SDP_UINT16, &feat);
2845         sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
2846
2847         sdp_set_info_attr(&record, "AVRCP TG", 0, 0);
2848
2849         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2850                 printf("Service Record registration failed\n");
2851                 ret = -1;
2852                 goto done;
2853         }
2854
2855         printf("Remote target service registered\n");
2856
2857 done:
2858         sdp_list_free(proto[0], 0);
2859         sdp_list_free(proto[1], 0);
2860         sdp_list_free(apseq, 0);
2861         sdp_list_free(aproto, 0);
2862
2863         return ret;
2864 }
2865
2866 static int add_udi_ue(sdp_session_t *session, svc_info_t *si)
2867 {
2868         sdp_record_t record;
2869         sdp_list_t *root, *svclass, *proto;
2870         uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
2871         uint8_t channel = si->channel ? si->channel: 18;
2872
2873         memset(&record, 0, sizeof(record));
2874         record.handle = si->handle;
2875
2876         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2877         root = sdp_list_append(NULL, &root_uuid);
2878         sdp_set_browse_groups(&record, root);
2879         sdp_list_free(root, NULL);
2880
2881         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2882         proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
2883
2884         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
2885         proto = sdp_list_append(proto, sdp_list_append(
2886                 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
2887
2888         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
2889
2890         sdp_uuid16_create(&svclass_uuid, UDI_MT_SVCLASS_ID);
2891         svclass = sdp_list_append(NULL, &svclass_uuid);
2892         sdp_set_service_classes(&record, svclass);
2893         sdp_list_free(svclass, NULL);
2894
2895         sdp_set_info_attr(&record, "UDI UE", NULL, NULL);
2896
2897         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2898                 printf("Service Record registration failed\n");
2899                 return -1;
2900         }
2901
2902         printf("UDI UE service registered\n");
2903
2904         return 0;
2905 }
2906
2907 static int add_udi_te(sdp_session_t *session, svc_info_t *si)
2908 {
2909         sdp_record_t record;
2910         sdp_list_t *root, *svclass, *proto;
2911         uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
2912         uint8_t channel = si->channel ? si->channel: 19;
2913
2914         memset(&record, 0, sizeof(record));
2915         record.handle = si->handle;
2916
2917         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2918         root = sdp_list_append(NULL, &root_uuid);
2919         sdp_set_browse_groups(&record, root);
2920         sdp_list_free(root, NULL);
2921
2922         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
2923         proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
2924
2925         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
2926         proto = sdp_list_append(proto, sdp_list_append(
2927                 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
2928
2929         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
2930
2931         sdp_uuid16_create(&svclass_uuid, UDI_TA_SVCLASS_ID);
2932         svclass = sdp_list_append(NULL, &svclass_uuid);
2933         sdp_set_service_classes(&record, svclass);
2934         sdp_list_free(svclass, NULL);
2935
2936         sdp_set_info_attr(&record, "UDI TE", NULL, NULL);
2937
2938         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2939                 printf("Service Record registration failed\n");
2940                 return -1;
2941         }
2942
2943         printf("UDI TE service registered\n");
2944
2945         return 0;
2946 }
2947
2948 static unsigned char sr1_uuid[] = {     0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0,
2949                                         0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 };
2950
2951 static int add_sr1(sdp_session_t *session, svc_info_t *si)
2952 {
2953         sdp_record_t record;
2954         sdp_list_t *root, *svclass;
2955         uuid_t root_uuid, svclass_uuid;
2956
2957         memset(&record, 0, sizeof(record));
2958         record.handle = si->handle;
2959
2960         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2961         root = sdp_list_append(NULL, &root_uuid);
2962         sdp_set_browse_groups(&record, root);
2963
2964         sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid);
2965         svclass = sdp_list_append(NULL, &svclass_uuid);
2966         sdp_set_service_classes(&record, svclass);
2967
2968         sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL);
2969
2970         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
2971                 printf("Service Record registration failed\n");
2972                 return -1;
2973         }
2974
2975         printf("Toshiba Speech Recognition SR-1 service record registered\n");
2976
2977         return 0;
2978 }
2979
2980 static unsigned char syncmls_uuid[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
2981                                         0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
2982
2983 static unsigned char syncmlc_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
2984                                         0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
2985
2986 static int add_syncml(sdp_session_t *session, svc_info_t *si)
2987 {
2988         sdp_record_t record;
2989         sdp_list_t *root, *svclass, *proto;
2990         uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
2991         uint8_t channel = si->channel ? si->channel: 15;
2992
2993         memset(&record, 0, sizeof(record));
2994         record.handle = si->handle;
2995
2996         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
2997         root = sdp_list_append(NULL, &root_uuid);
2998         sdp_set_browse_groups(&record, root);
2999
3000         sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid);
3001         svclass = sdp_list_append(NULL, &svclass_uuid);
3002         sdp_set_service_classes(&record, svclass);
3003
3004         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3005         proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3006
3007         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3008         proto = sdp_list_append(proto, sdp_list_append(
3009                 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3010
3011         sdp_uuid16_create(&obex_uuid, OBEX_UUID);
3012         proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid));
3013
3014         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3015
3016         sdp_set_info_attr(&record, "SyncML Client", NULL, NULL);
3017
3018         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3019                 printf("Service Record registration failed\n");
3020                 return -1;
3021         }
3022
3023         printf("SyncML Client service record registered\n");
3024
3025         return 0;
3026 }
3027
3028 static unsigned char async_uuid[] = {   0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62,
3029                                         0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C };
3030
3031 static int add_activesync(sdp_session_t *session, svc_info_t *si)
3032 {
3033         sdp_record_t record;
3034         sdp_list_t *root, *svclass, *proto;
3035         uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
3036         uint8_t channel = si->channel ? si->channel: 21;
3037
3038         memset(&record, 0, sizeof(record));
3039         record.handle = si->handle;
3040
3041         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3042         root = sdp_list_append(NULL, &root_uuid);
3043         sdp_set_browse_groups(&record, root);
3044
3045         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3046         proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3047
3048         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3049         proto = sdp_list_append(proto, sdp_list_append(
3050         sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3051
3052         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3053
3054         sdp_uuid128_create(&svclass_uuid, (void *) async_uuid);
3055         svclass = sdp_list_append(NULL, &svclass_uuid);
3056         sdp_set_service_classes(&record, svclass);
3057
3058         sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL);
3059
3060         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3061                 printf("Service Record registration failed\n");
3062                 return -1;
3063         }
3064
3065         printf("ActiveSync service record registered\n");
3066
3067         return 0;
3068 }
3069
3070 static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
3071                                         0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
3072
3073 static int add_hotsync(sdp_session_t *session, svc_info_t *si)
3074 {
3075         sdp_record_t record;
3076         sdp_list_t *root, *svclass, *proto;
3077         uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
3078         uint8_t channel = si->channel ? si->channel: 22;
3079
3080         memset(&record, 0, sizeof(record));
3081         record.handle = si->handle;
3082
3083         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3084         root = sdp_list_append(NULL, &root_uuid);
3085         sdp_set_browse_groups(&record, root);
3086
3087         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3088         proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3089
3090         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3091         proto = sdp_list_append(proto, sdp_list_append(
3092         sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3093
3094         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3095
3096         sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
3097         svclass = sdp_list_append(NULL, &svclass_uuid);
3098         sdp_set_service_classes(&record, svclass);
3099
3100         sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
3101
3102         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3103                 printf("Service Record registration failed\n");
3104                 return -1;
3105         }
3106
3107         printf("HotSync service record registered\n");
3108
3109         return 0;
3110 }
3111
3112 static unsigned char palmos_uuid[] = {  0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51,
3113                                         0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 };
3114
3115 static int add_palmos(sdp_session_t *session, svc_info_t *si)
3116 {
3117         sdp_record_t record;
3118         sdp_list_t *root, *svclass;
3119         uuid_t root_uuid, svclass_uuid;
3120
3121         memset(&record, 0, sizeof(record));
3122         record.handle = si->handle;
3123
3124         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3125         root = sdp_list_append(NULL, &root_uuid);
3126         sdp_set_browse_groups(&record, root);
3127
3128         sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid);
3129         svclass = sdp_list_append(NULL, &svclass_uuid);
3130         sdp_set_service_classes(&record, svclass);
3131
3132         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3133                 printf("Service Record registration failed\n");
3134                 return -1;
3135         }
3136
3137         printf("PalmOS service record registered\n");
3138
3139         return 0;
3140 }
3141
3142 static unsigned char nokid_uuid[] = {   0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00,
3143                                         0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3144
3145 static int add_nokiaid(sdp_session_t *session, svc_info_t *si)
3146 {
3147         sdp_record_t record;
3148         sdp_list_t *root, *svclass;
3149         uuid_t root_uuid, svclass_uuid;
3150         uint16_t verid = 0x005f;
3151         sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid);
3152
3153         memset(&record, 0, sizeof(record));
3154         record.handle = si->handle;
3155
3156         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3157         root = sdp_list_append(NULL, &root_uuid);
3158         sdp_set_browse_groups(&record, root);
3159
3160         sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid);
3161         svclass = sdp_list_append(NULL, &svclass_uuid);
3162         sdp_set_service_classes(&record, svclass);
3163
3164         sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version);
3165
3166         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3167                 printf("Service Record registration failed\n");
3168                 sdp_data_free(version);
3169                 return -1;
3170         }
3171
3172         printf("Nokia ID service record registered\n");
3173
3174         return 0;
3175 }
3176
3177 static unsigned char pcsuite_uuid[] = { 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00,
3178                                         0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3179
3180 static int add_pcsuite(sdp_session_t *session, svc_info_t *si)
3181 {
3182         sdp_record_t record;
3183         sdp_list_t *root, *svclass, *proto;
3184         uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
3185         uint8_t channel = si->channel ? si->channel: 14;
3186
3187         memset(&record, 0, sizeof(record));
3188         record.handle = si->handle;
3189
3190         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3191         root = sdp_list_append(NULL, &root_uuid);
3192         sdp_set_browse_groups(&record, root);
3193
3194         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3195         proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3196
3197         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3198         proto = sdp_list_append(proto, sdp_list_append(
3199                 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3200
3201         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3202
3203         sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid);
3204         svclass = sdp_list_append(NULL, &svclass_uuid);
3205         sdp_set_service_classes(&record, svclass);
3206
3207         sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL);
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("Nokia PC Suite service registered\n");
3215
3216         return 0;
3217 }
3218
3219 static unsigned char nftp_uuid[] = {    0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00,
3220                                         0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3221
3222 static unsigned char nsyncml_uuid[] = { 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x10, 0x00,
3223                                         0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3224
3225 static unsigned char ngage_uuid[] = {   0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00,
3226                                         0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3227
3228 static unsigned char apple_uuid[] = {   0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90,
3229                                         0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 };
3230
3231 static int add_apple(sdp_session_t *session, svc_info_t *si)
3232 {
3233         sdp_record_t record;
3234         sdp_list_t *root;
3235         uuid_t root_uuid;
3236         uint32_t attr783 = 0x00000000;
3237         uint32_t attr785 = 0x00000002;
3238         uint16_t attr786 = 0x1234;
3239
3240         memset(&record, 0, sizeof(record));
3241         record.handle = si->handle;
3242
3243         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3244         root = sdp_list_append(NULL, &root_uuid);
3245         sdp_set_browse_groups(&record, root);
3246
3247         sdp_attr_add_new(&record, 0x0780, SDP_UUID128, (void *) apple_uuid);
3248         sdp_attr_add_new(&record, 0x0781, SDP_TEXT_STR8, (void *) "Macmini");
3249         sdp_attr_add_new(&record, 0x0782, SDP_TEXT_STR8, (void *) "PowerMac10,1");
3250         sdp_attr_add_new(&record, 0x0783, SDP_UINT32, (void *) &attr783);
3251         sdp_attr_add_new(&record, 0x0784, SDP_TEXT_STR8, (void *) "1.6.6f22");
3252         sdp_attr_add_new(&record, 0x0785, SDP_UINT32, (void *) &attr785);
3253         sdp_attr_add_new(&record, 0x0786, SDP_UUID16, (void *) &attr786);
3254
3255         sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL);
3256
3257         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3258                 printf("Service Record registration failed\n");
3259                 return -1;
3260         }
3261
3262         printf("Apple attribute service registered\n");
3263
3264         return 0;
3265 }
3266
3267 static int add_isync(sdp_session_t *session, svc_info_t *si)
3268 {
3269         sdp_record_t record;
3270         sdp_list_t *root, *svclass, *proto;
3271         uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid;
3272         uint8_t channel = si->channel ? si->channel : 16;
3273
3274         memset(&record, 0, sizeof(record));
3275         record.handle = si->handle;
3276
3277         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3278         root = sdp_list_append(NULL, &root_uuid);
3279         sdp_set_browse_groups(&record, root);
3280
3281         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3282         proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
3283
3284         sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3285         proto = sdp_list_append(proto, sdp_list_append(
3286                 sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
3287
3288         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3289
3290         sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID);
3291         svclass = sdp_list_append(NULL, &serial_uuid);
3292
3293         sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID);
3294         svclass = sdp_list_append(svclass, &svclass_uuid);
3295
3296         sdp_set_service_classes(&record, svclass);
3297
3298         sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd.");
3299
3300         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3301                 printf("Service Record registration failed\n");
3302                 return -1;
3303         }
3304
3305         printf("Apple iSync service registered\n");
3306
3307         return 0;
3308 }
3309
3310 static int add_semchla(sdp_session_t *session, svc_info_t *si)
3311 {
3312         sdp_record_t record;
3313         sdp_profile_desc_t profile;
3314         sdp_list_t *root, *svclass, *proto, *profiles;
3315         uuid_t root_uuid, service_uuid, l2cap_uuid, semchla_uuid;
3316         uint16_t psm = 0xf0f9;
3317
3318         memset(&record, 0, sizeof(record));
3319         record.handle = si->handle;
3320
3321         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3322         root = sdp_list_append(NULL, &root_uuid);
3323         sdp_set_browse_groups(&record, root);
3324
3325         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3326         proto = sdp_list_append(NULL, sdp_list_append(
3327                 sdp_list_append(NULL, &l2cap_uuid), sdp_data_alloc(SDP_UINT16, &psm)));
3328
3329         sdp_uuid32_create(&semchla_uuid, 0x8e770300);
3330         proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid));
3331
3332         sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
3333
3334         sdp_uuid32_create(&service_uuid, 0x8e771301);
3335         svclass = sdp_list_append(NULL, &service_uuid);
3336
3337         sdp_set_service_classes(&record, svclass);
3338
3339         sdp_uuid32_create(&profile.uuid, 0x8e771302);   // Headset
3340         //sdp_uuid32_create(&profile.uuid, 0x8e771303); // Phone
3341         profile.version = 0x0100;
3342         profiles = sdp_list_append(NULL, &profile);
3343         sdp_set_profile_descs(&record, profiles);
3344
3345         sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL);
3346
3347         if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
3348                 printf("Service Record registration failed\n");
3349                 return -1;
3350         }
3351
3352         /* SEMC High Level Authentication */
3353         printf("SEMC HLA service registered\n");
3354
3355         return 0;
3356 }
3357
3358 struct {
3359         char            *name;
3360         uint32_t        class;
3361         int             (*add)(sdp_session_t *sess, svc_info_t *si);
3362         unsigned char *uuid;
3363 } service[] = {
3364         { "DID",        PNP_INFO_SVCLASS_ID,            NULL,           },
3365
3366         { "SP",         SERIAL_PORT_SVCLASS_ID,         add_sp          },
3367         { "DUN",        DIALUP_NET_SVCLASS_ID,          add_dun         },
3368         { "LAN",        LAN_ACCESS_SVCLASS_ID,          add_lan         },
3369         { "FAX",        FAX_SVCLASS_ID,                 add_fax         },
3370         { "OPUSH",      OBEX_OBJPUSH_SVCLASS_ID,        add_opush       },
3371         { "FTP",        OBEX_FILETRANS_SVCLASS_ID,      add_ftp         },
3372         { "PRINT",      DIRECT_PRINTING_SVCLASS_ID,     add_directprint },
3373
3374         { "HS",         HEADSET_SVCLASS_ID,             add_headset     },
3375         { "HSAG",       HEADSET_AGW_SVCLASS_ID, add_headset_ag},
3376         { "HF",         HANDSFREE_SVCLASS_ID,           add_handsfree   },
3377         { "HFAG",       HANDSFREE_AGW_SVCLASS_ID,       add_handsfree_ag},
3378         { "SAP",        SAP_SVCLASS_ID,                 add_simaccess   },
3379
3380         { "NAP",        NAP_SVCLASS_ID,                 add_nap         },
3381         { "GN",         GN_SVCLASS_ID,                  add_gn          },
3382         { "PANU",       PANU_SVCLASS_ID,                add_panu        },
3383
3384         { "HCRP",       HCR_SVCLASS_ID,                 NULL            },
3385         { "HID",        HID_SVCLASS_ID,                 NULL            },
3386         { "KEYB",       HID_SVCLASS_ID,                 add_hid_keyb    },
3387         { "WIIMOTE",    HID_SVCLASS_ID,                 add_hid_wiimote },
3388         { "CIP",        CIP_SVCLASS_ID,                 add_cip         },
3389         { "CTP",        CORDLESS_TELEPHONY_SVCLASS_ID,  add_ctp         },
3390
3391         { "A2SRC",      AUDIO_SOURCE_SVCLASS_ID,        add_a2source    },
3392         { "A2SNK",      AUDIO_SINK_SVCLASS_ID,          add_a2sink      },
3393         { "AVRCT",      AV_REMOTE_SVCLASS_ID,           add_avrct       },
3394         { "AVRTG",      AV_REMOTE_TARGET_SVCLASS_ID,    add_avrtg       },
3395
3396         { "UDIUE",      UDI_MT_SVCLASS_ID,              add_udi_ue      },
3397         { "UDITE",      UDI_TA_SVCLASS_ID,              add_udi_te      },
3398
3399         { "SEMCHLA",    0x8e771301,                     add_semchla     },
3400
3401         { "SR1",        0,                              add_sr1,        sr1_uuid        },
3402         { "SYNCML",     0,                              add_syncml,     syncmlc_uuid    },
3403         { "SYNCMLSERV", 0,                              NULL,           syncmls_uuid    },
3404         { "ACTIVESYNC", 0,                              add_activesync, async_uuid      },
3405         { "HOTSYNC",    0,                              add_hotsync,    hotsync_uuid    },
3406         { "PALMOS",     0,                              add_palmos,     palmos_uuid     },
3407         { "NOKID",      0,                              add_nokiaid,    nokid_uuid      },
3408         { "PCSUITE",    0,                              add_pcsuite,    pcsuite_uuid    },
3409         { "NFTP",       0,                              NULL,           nftp_uuid       },
3410         { "NSYNCML",    0,                              NULL,           nsyncml_uuid    },
3411         { "NGAGE",      0,                              NULL,           ngage_uuid      },
3412         { "APPLE",      0,                              add_apple,      apple_uuid      },
3413
3414         { "ISYNC",      APPLE_AGENT_SVCLASS_ID,         add_isync,      },
3415
3416         { 0 }
3417 };
3418
3419 /* Add local service */
3420 static int add_service(bdaddr_t *bdaddr, svc_info_t *si)
3421 {
3422         sdp_session_t *sess;
3423         int i, ret = -1;
3424
3425         if (!si->name)
3426                 return -1;
3427
3428         sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
3429         if (!sess)
3430                 return -1;
3431
3432         for (i = 0; service[i].name; i++)
3433                 if (!strcasecmp(service[i].name, si->name)) {
3434                         if (service[i].add)
3435                                 ret = service[i].add(sess, si);
3436                         goto done;
3437                 }
3438
3439         printf("Unknown service name: %s\n", si->name);
3440
3441 done:
3442         free(si->name);
3443         sdp_close(sess);
3444
3445         return ret;
3446 }
3447
3448 static struct option add_options[] = {
3449         { "help",       0, 0, 'h' },
3450         { "handle",     1, 0, 'r' },
3451         { "psm",        1, 0, 'p' },
3452         { "channel",    1, 0, 'c' },
3453         { "network",    1, 0, 'n' },
3454         { 0, 0, 0, 0 }
3455 };
3456
3457 static char *add_help = 
3458         "Usage:\n"
3459         "\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n";
3460
3461 static int cmd_add(int argc, char **argv)
3462 {
3463         svc_info_t si;
3464         int opt;
3465
3466         memset(&si, 0, sizeof(si));
3467         si.handle = 0xffffffff;
3468
3469         for_each_opt(opt, add_options, 0) {
3470                 switch (opt) {
3471                 case 'r':
3472                         if (strncasecmp(optarg, "0x", 2))
3473                                 si.handle = atoi(optarg);
3474                         else
3475                                 si.handle = strtol(optarg + 2, NULL, 16);
3476                         break;
3477                 case 'p':
3478                         if (strncasecmp(optarg, "0x", 2))
3479                                 si.psm = atoi(optarg);
3480                         else
3481                                 si.psm = strtol(optarg + 2, NULL, 16);
3482                         break;
3483                 case 'c':
3484                         if (strncasecmp(optarg, "0x", 2))
3485                                 si.channel = atoi(optarg);
3486                         else
3487                                 si.channel = strtol(optarg + 2, NULL, 16);
3488                         break;
3489                 case 'n':
3490                         if (strncasecmp(optarg, "0x", 2))
3491                                 si.network = atoi(optarg);
3492                         else
3493                                 si.network = strtol(optarg + 2, NULL, 16);
3494                         break;
3495                 default:
3496                         printf(add_help);
3497                         return -1;
3498                 }
3499         }
3500
3501         argc -= optind;
3502         argv += optind;
3503
3504         if (argc < 1) {
3505                 printf(add_help);
3506                 return -1;
3507         }
3508
3509         si.name = strdup(argv[0]);
3510
3511         return add_service(0, &si);
3512 }
3513
3514 /* Delete local service */
3515 static int del_service(bdaddr_t *bdaddr, void *arg)
3516 {
3517         uint32_t handle, range = 0x0000ffff;
3518         sdp_list_t *attr;
3519         sdp_session_t *sess;
3520         sdp_record_t *rec;
3521
3522         if (!arg) { 
3523                 printf("Record handle was not specified.\n");
3524                 return -1;
3525         }
3526
3527         sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
3528         if (!sess) {
3529                 printf("No local SDP server!\n");
3530                 return -1;
3531         }
3532
3533         handle = strtoul((char *)arg, 0, 16);
3534         attr = sdp_list_append(0, &range);
3535         rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
3536         sdp_list_free(attr, 0);
3537
3538         if (!rec) {
3539                 printf("Service Record not found.\n");
3540                 sdp_close(sess);
3541                 return -1;
3542         }
3543
3544         if (sdp_device_record_unregister(sess, &interface, rec)) {
3545                 printf("Failed to unregister service record: %s\n", strerror(errno));
3546                 sdp_close(sess);
3547                 return -1;
3548         }
3549
3550         printf("Service Record deleted.\n");
3551         sdp_close(sess);
3552
3553         return 0;
3554 }
3555
3556 static struct option del_options[] = {
3557         { "help",       0, 0, 'h' },
3558         { 0, 0, 0, 0 }
3559 };
3560
3561 static char *del_help = 
3562         "Usage:\n"
3563         "\tdel record_handle\n";
3564
3565 static int cmd_del(int argc, char **argv)
3566 {
3567         int opt;
3568
3569         for_each_opt(opt, del_options, 0) {
3570                 switch (opt) {
3571                 default:
3572                         printf(del_help);
3573                         return -1;
3574                 }
3575         }
3576
3577         argc -= optind;
3578         argv += optind;
3579
3580         if (argc < 1) {
3581                 printf(del_help);
3582                 return -1;
3583         }
3584
3585         return del_service(NULL, argv[0]);
3586 }
3587
3588 /*
3589  * Perform an inquiry and search/browse all peer found.
3590  */
3591 static void inquiry(handler_t handler, void *arg)
3592 {
3593         inquiry_info ii[20];
3594         uint8_t count = 0;
3595         int i;
3596
3597         printf("Inquiring ...\n");
3598         if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
3599                 printf("Inquiry failed\n");
3600                 return;
3601         }
3602
3603         for (i = 0; i < count; i++)
3604                 handler(&ii[i].bdaddr, arg);
3605 }
3606
3607 static void doprintf(void *data, const char *str)
3608 {
3609         printf(str);
3610 }
3611
3612 /*
3613  * Search for a specific SDP service
3614  */
3615 static int do_search(bdaddr_t *bdaddr, struct search_context *context)
3616 {
3617         sdp_list_t *attrid, *search, *seq, *next;
3618         uint32_t range = 0x0000ffff;
3619         char str[20];
3620         sdp_session_t *sess;
3621
3622         if (!bdaddr) {
3623                 inquiry(do_search, context);
3624                 return 0;
3625         }
3626
3627         sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
3628         ba2str(bdaddr, str);
3629         if (!sess) {
3630                 printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
3631                 return -1;
3632         }
3633
3634         if (context->view != RAW_VIEW) {
3635                 if (context->svc)
3636                         printf("Searching for %s on %s ...\n", context->svc, str);
3637                 else
3638                         printf("Browsing %s ...\n", str);
3639         }
3640
3641         attrid = sdp_list_append(0, &range);
3642         search = sdp_list_append(0, &context->group);
3643         if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) {
3644                 printf("Service Search failed: %s\n", strerror(errno));
3645                 sdp_close(sess);
3646                 return -1;
3647         }
3648         sdp_list_free(attrid, 0);
3649         sdp_list_free(search, 0);
3650
3651         for (; seq; seq = next) {
3652                 sdp_record_t *rec = (sdp_record_t *) seq->data;
3653                 struct search_context sub_context;
3654
3655                 switch (context->view) {
3656                 case DEFAULT_VIEW:
3657                         /* Display user friendly form */
3658                         print_service_attr(rec);
3659                         printf("\n");
3660                         break;
3661                 case TREE_VIEW:
3662                         /* Display full tree */
3663                         print_tree_attr(rec);
3664                         printf("\n");
3665                         break;
3666                 case XML_VIEW:
3667                         /* Display raw XML tree */
3668                         convert_sdp_record_to_xml(rec, 0, doprintf);
3669                         break;
3670                 default:
3671                         /* Display raw tree */
3672                         print_raw_attr(rec);
3673                         break;
3674                 }
3675
3676                 if (sdp_get_group_id(rec, &sub_context.group) != -1) {
3677                         /* Set the subcontext for browsing the sub tree */
3678                         memcpy(&sub_context, context, sizeof(struct search_context));
3679                         /* Browse the next level down if not done */
3680                         if (sub_context.group.value.uuid16 != context->group.value.uuid16)
3681                                 do_search(bdaddr, &sub_context);
3682                 }
3683                 next = seq->next;
3684                 free(seq);
3685                 sdp_record_free(rec);
3686         }
3687
3688         sdp_close(sess);
3689         return 0;
3690 }
3691
3692 static struct option browse_options[] = {
3693         { "help",       0, 0, 'h' },
3694         { "tree",       0, 0, 't' },
3695         { "raw",        0, 0, 'r' },
3696         { "xml",        0, 0, 'x' },
3697         { "uuid",       1, 0, 'u' },
3698         { "l2cap",      0, 0, 'l' },
3699         { 0, 0, 0, 0 }
3700 };
3701
3702 static char *browse_help = 
3703         "Usage:\n"
3704         "\tbrowse [--tree] [--raw] [--xml] [--uuid uuid] [--l2cap] [bdaddr]\n";
3705
3706 /*
3707  * Browse the full SDP database (i.e. list all services starting from the
3708  * root/top-level).
3709  */
3710 static int cmd_browse(int argc, char **argv)
3711 {
3712         struct search_context context;
3713         int opt, num;
3714
3715         /* Initialise context */
3716         memset(&context, '\0', sizeof(struct search_context));
3717         /* We want to browse the top-level/root */
3718         sdp_uuid16_create(&context.group, PUBLIC_BROWSE_GROUP);
3719
3720         for_each_opt(opt, browse_options, 0) {
3721                 switch (opt) {
3722                 case 't':
3723                         context.view = TREE_VIEW;
3724                         break;
3725                 case 'r':
3726                         context.view = RAW_VIEW;
3727                         break;
3728                 case 'x':
3729                         context.view = XML_VIEW;
3730                         break;
3731                 case 'u':
3732                         if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) {
3733                                 printf("Invalid uuid %s\n", optarg);
3734                                 return -1;
3735                         }
3736                         sdp_uuid16_create(&context.group, num);
3737                         break;
3738                 case 'l':
3739                         sdp_uuid16_create(&context.group, L2CAP_UUID);
3740                         break;
3741                 default:
3742                         printf(browse_help);
3743                         return -1;
3744                 }
3745         }
3746
3747         argc -= optind;
3748         argv += optind;
3749
3750         if (argc >= 1) {
3751                 bdaddr_t bdaddr;
3752                 estr2ba(argv[0], &bdaddr);
3753                 return do_search(&bdaddr, &context);
3754         }
3755
3756         return do_search(NULL, &context);
3757 }
3758
3759 static struct option search_options[] = {
3760         { "help",       0, 0, 'h' },
3761         { "bdaddr",     1, 0, 'b' },
3762         { "tree",       0, 0, 't' },
3763         { "raw",        0, 0, 'r' },
3764         { "xml",        0, 0, 'x' },
3765         { 0, 0, 0, 0}
3766 };
3767
3768 static char *search_help = 
3769         "Usage:\n"
3770         "\tsearch [--bdaddr bdaddr] [--tree] [--raw] [--xml] SERVICE\n"
3771         "SERVICE is a name (string) or UUID (0x1002)\n";
3772
3773 /*
3774  * Search for a specific SDP service
3775  *
3776  * Note : we should support multiple services on the command line :
3777  *          sdptool search 0x0100 0x000f 0x1002
3778  * (this would search a service supporting both L2CAP and BNEP directly in
3779  * the top level browse group)
3780  */
3781 static int cmd_search(int argc, char **argv)
3782 {
3783         struct search_context context;
3784         unsigned char *uuid = NULL;
3785         uint32_t class = 0;
3786         bdaddr_t bdaddr;
3787         int has_addr = 0;
3788         int i;
3789         int opt;
3790
3791         /* Initialise context */
3792         memset(&context, '\0', sizeof(struct search_context));
3793
3794         for_each_opt(opt, search_options, 0) {
3795                 switch (opt) {
3796                 case 'b':
3797                         estr2ba(optarg, &bdaddr);
3798                         has_addr = 1;
3799                         break;
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                 default:
3810                         printf(search_help);
3811                         return -1;
3812                 }
3813         }
3814
3815         argc -= optind;
3816         argv += optind;
3817
3818         if (argc < 1) {
3819                 printf(search_help);
3820                 return -1;
3821         }
3822
3823         /* Note : we need to find a way to support search combining
3824          * multiple services */
3825         context.svc = strdup(argv[0]);
3826         if (!strncasecmp(context.svc, "0x", 2)) {
3827                 int num;
3828                 /* This is a UUID16, just convert to int */
3829                 sscanf(context.svc + 2, "%X", &num);
3830                 class = num;
3831                 printf("Class 0x%X\n", class);
3832         } else {
3833                 /* Convert class name to an UUID */
3834
3835                 for (i = 0; service[i].name; i++)
3836                         if (strcasecmp(context.svc, service[i].name) == 0) {
3837                                 class = service[i].class;
3838                                 uuid = service[i].uuid;
3839                                 break;
3840                         }
3841                 if (!class && !uuid) {
3842                         printf("Unknown service %s\n", context.svc);
3843                         return -1;
3844                 }
3845         }
3846
3847         if (class) {
3848                 if (class & 0xffff0000)
3849                         sdp_uuid32_create(&context.group, class);
3850                 else {
3851                         uint16_t class16 = class & 0xffff;
3852                         sdp_uuid16_create(&context.group, class16);
3853                 }
3854         } else
3855                 sdp_uuid128_create(&context.group, uuid);
3856
3857         if (has_addr)
3858                 return do_search(&bdaddr, &context);
3859
3860         return do_search(NULL, &context);
3861 }
3862
3863 /*
3864  * Show how to get a specific SDP record by its handle.
3865  * Not really useful to the user, just show how it can be done...
3866  */
3867 static int get_service(bdaddr_t *bdaddr, struct search_context *context, int quite)
3868 {
3869         sdp_list_t *attrid;
3870         uint32_t range = 0x0000ffff;
3871         sdp_record_t *rec;
3872         sdp_session_t *session = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
3873
3874         if (!session) {
3875                 char str[20];
3876                 ba2str(bdaddr, str);
3877                 printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
3878                 return -1;
3879         }
3880
3881         attrid = sdp_list_append(0, &range);
3882         rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid);
3883         sdp_list_free(attrid, 0);
3884         sdp_close(session);
3885
3886         if (!rec) {
3887                 if (!quite) {
3888                         printf("Service get request failed.\n");
3889                         return -1;
3890                 } else
3891                         return 0;
3892         }
3893
3894         switch (context->view) {
3895         case DEFAULT_VIEW:
3896                 /* Display user friendly form */
3897                 print_service_attr(rec);
3898                 printf("\n");
3899                 break;
3900         case TREE_VIEW:
3901                 /* Display full tree */
3902                 print_tree_attr(rec);
3903                 printf("\n");
3904                 break;
3905         case XML_VIEW:
3906                 /* Display raw XML tree */
3907                 convert_sdp_record_to_xml(rec, 0, doprintf);
3908                 break;
3909         default:
3910                 /* Display raw tree */
3911                 print_raw_attr(rec);
3912                 break;
3913         }
3914
3915         sdp_record_free(rec);
3916         return 0;
3917 }
3918
3919 static struct option records_options[] = {
3920         { "help",       0, 0, 'h' },
3921         { "tree",       0, 0, 't' },
3922         { "raw",        0, 0, 'r' },
3923         { "xml",        0, 0, 'x' },
3924         { 0, 0, 0, 0 }
3925 };
3926
3927 static char *records_help = 
3928         "Usage:\n"
3929         "\trecords [--tree] [--raw] [--xml] bdaddr\n";
3930
3931 /*
3932  * Request possible SDP service records
3933  */
3934 static int cmd_records(int argc, char **argv)
3935 {
3936         struct search_context context;
3937         uint32_t base[] = { 0x10000, 0x10300, 0x10500,
3938                         0x1002e, 0x110b, 0x90000, 0x2008000,
3939                         0x4000000, 0x100000, 0x1000000, 0x4f491100 };
3940         bdaddr_t bdaddr;
3941         int i, n, opt, err = 0, num = 32;
3942
3943         /* Initialise context */
3944         memset(&context, '\0', sizeof(struct search_context));
3945
3946         for_each_opt(opt, records_options, 0) {
3947                 switch (opt) {
3948                 case 't':
3949                         context.view = TREE_VIEW;
3950                         break;
3951                 case 'r':
3952                         context.view = RAW_VIEW;
3953                         break;
3954                 case 'x':
3955                         context.view = XML_VIEW;
3956                         break;
3957                 default:
3958                         printf(records_help);
3959                         return -1;
3960                 }
3961         }
3962
3963         argc -= optind;
3964         argv += optind;
3965
3966         if (argc < 1) {
3967                 printf(records_help);
3968                 return -1;
3969         }
3970
3971         /* Convert command line parameters */
3972         estr2ba(argv[0], &bdaddr);
3973
3974         for (i = 0; i < sizeof(base) / sizeof(uint32_t); i++)
3975                 for (n = 0; n < num; n++) {
3976                         context.handle = base[i] + n;
3977                         err = get_service(&bdaddr, &context, 1);
3978                         if (err < 0)
3979                                 goto done;
3980                 }
3981
3982 done:
3983         return 0;
3984 }
3985
3986 static struct option get_options[] = {
3987         { "help",       0, 0, 'h' },
3988         { "bdaddr",     1, 0, 'b' },
3989         { "tree",       0, 0, 't' },
3990         { "raw",        0, 0, 'r' },
3991         { "xml",        0, 0, 'x' },
3992         { 0, 0, 0, 0 }
3993 };
3994
3995 static char *get_help = 
3996         "Usage:\n"
3997         "\tget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\n";
3998
3999 /*
4000  * Get a specific SDP record on the local SDP server
4001  */
4002 static int cmd_get(int argc, char **argv)
4003 {
4004         struct search_context context;
4005         bdaddr_t bdaddr;
4006         int has_addr = 0;
4007         int opt;
4008
4009         /* Initialise context */
4010         memset(&context, '\0', sizeof(struct search_context));
4011
4012         for_each_opt(opt, get_options, 0) {
4013                 switch (opt) {
4014                 case 'b':
4015                         estr2ba(optarg, &bdaddr);
4016                         has_addr = 1;
4017                         break;
4018                 case 't':
4019                         context.view = TREE_VIEW;
4020                         break;
4021                 case 'r':
4022                         context.view = RAW_VIEW;
4023                         break;
4024                 case 'x':
4025                         context.view = XML_VIEW;
4026                         break;
4027                 default:
4028                         printf(get_help);
4029                         return -1;
4030                 }
4031         }
4032
4033         argc -= optind;
4034         argv += optind;
4035
4036         if (argc < 1) {
4037                 printf(get_help);
4038                 return -1;
4039         }
4040
4041         /* Convert command line parameters */
4042         context.handle = strtoul(argv[0], 0, 16);
4043
4044         return get_service(has_addr ? &bdaddr : BDADDR_LOCAL, &context, 0);
4045 }
4046
4047 static struct {
4048         char *cmd;
4049         int (*func)(int argc, char **argv);
4050         char *doc;
4051 } command[] = {
4052         { "search",  cmd_search,      "Search for a service"          },
4053         { "browse",  cmd_browse,      "Browse all available services" },
4054         { "records", cmd_records,     "Request all records"           },
4055         { "add",     cmd_add,         "Add local service"             },
4056         { "del",     cmd_del,         "Delete local service"          },
4057         { "get",     cmd_get,         "Get local service"             },
4058         { "setattr", cmd_setattr,     "Set/Add attribute to a SDP record"          },
4059         { "setseq",  cmd_setseq,      "Set/Add attribute sequence to a SDP record" },
4060         { 0, 0, 0 }
4061 };
4062
4063 static void usage(void)
4064 {
4065         int i, pos = 0;
4066
4067         printf("sdptool - SDP tool v%s\n", VERSION);
4068         printf("Usage:\n"
4069                 "\tsdptool [options] <command> [command parameters]\n");
4070         printf("Options:\n"
4071                 "\t-h\t\tDisplay help\n"
4072                 "\t-i\t\tSpecify source interface\n");
4073
4074         printf("Commands:\n");
4075         for (i = 0; command[i].cmd; i++)
4076                 printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc);
4077
4078         printf("\nServices:\n\t");
4079         for (i = 0; service[i].name; i++) {
4080                 printf("%s ", service[i].name);
4081                 pos += strlen(service[i].name) + 1;
4082                 if (pos > 60) {
4083                         printf("\n\t");
4084                         pos = 0;
4085                 }
4086         }
4087         printf("\n");
4088 }
4089
4090 static struct option main_options[] = {
4091         { "help",       0, 0, 'h' },
4092         { "device",     1, 0, 'i' },
4093         { 0, 0, 0, 0 }
4094 };
4095
4096 int main(int argc, char *argv[])
4097 {
4098         int i, opt;
4099
4100         bacpy(&interface, BDADDR_ANY);
4101
4102         while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
4103                 switch(opt) {
4104                 case 'i':
4105                         if (!strncmp(optarg, "hci", 3))
4106                                 hci_devba(atoi(optarg + 3), &interface);
4107                         else
4108                                 str2ba(optarg, &interface);
4109                         break;
4110
4111                 case 'h':
4112                         usage();
4113                         exit(0);
4114
4115                 default:
4116                         exit(1);
4117                 }
4118         }
4119
4120         argc -= optind;
4121         argv += optind;
4122         optind = 0;
4123
4124         if (argc < 1) {
4125                 usage();
4126                 exit(1);
4127         }
4128
4129         for (i = 0; command[i].cmd; i++)
4130                 if (strncmp(command[i].cmd, argv[0], 4) == 0)
4131                         return command[i].func(argc, argv);
4132
4133         return 1;
4134 }