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