• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
estr2ba(char * str,bdaddr_t * ba)59 static int estr2ba(char *str, bdaddr_t *ba)
60 {
61 	/* Only trap "local", "any" is already dealt with */
62 	if(!strcmp(str, "local")) {
63 		bacpy(ba, BDADDR_LOCAL);
64 		return 0;
65 	}
66 	return str2ba(str, ba);
67 }
68 
69 #define DEFAULT_VIEW	0	/* Display only known attribute */
70 #define TREE_VIEW	1	/* Display full attribute tree */
71 #define RAW_VIEW	2	/* Display raw tree */
72 #define XML_VIEW	3	/* Display xml tree */
73 
74 /* Pass args to the inquiry/search handler */
75 struct search_context {
76 	char		*svc;		/* Service */
77 	uuid_t		group;		/* Browse group */
78 	int		view;		/* View mode */
79 	uint32_t	handle;		/* Service record handle */
80 };
81 
82 typedef int (*handler_t)(bdaddr_t *bdaddr, struct search_context *arg);
83 
84 static char UUID_str[MAX_LEN_UUID_STR];
85 static bdaddr_t interface;
86 
87 /* Definition of attribute members */
88 struct member_def {
89 	char *name;
90 };
91 
92 /* Definition of an attribute */
93 struct attrib_def {
94 	int			num;		/* Numeric ID - 16 bits */
95 	char			*name;		/* User readable name */
96 	struct member_def	*members;	/* Definition of attribute args */
97 	int			member_max;	/* Max of attribute arg definitions */
98 };
99 
100 /* Definition of a service or protocol */
101 struct uuid_def {
102 	int			num;		/* Numeric ID - 16 bits */
103 	char			*name;		/* User readable name */
104 	struct attrib_def	*attribs;	/* Specific attribute definitions */
105 	int			attrib_max;	/* Max of attribute definitions */
106 };
107 
108 /* Context information about current attribute */
109 struct attrib_context {
110 	struct uuid_def		*service;	/* Service UUID, if known */
111 	struct attrib_def	*attrib;	/* Description of the attribute */
112 	int			member_index;	/* Index of current attribute member */
113 };
114 
115 /* Context information about the whole service */
116 struct service_context {
117 	struct uuid_def		*service;	/* Service UUID, if known */
118 };
119 
120 /* Allow us to do nice formatting of the lists */
121 static char *indent_spaces = "                                         ";
122 
123 /* ID of the service attribute.
124  * Most attributes after 0x200 are defined based on the service, so
125  * we need to find what is the service (which is messy) - Jean II */
126 #define SERVICE_ATTR	0x1
127 
128 /* Definition of the optional arguments in protocol list */
129 static struct member_def protocol_members[] = {
130 	{ "Protocol"		},
131 	{ "Channel/Port"	},
132 	{ "Version"		},
133 };
134 
135 /* Definition of the optional arguments in profile list */
136 static struct member_def profile_members[] = {
137 	{ "Profile"	},
138 	{ "Version"	},
139 };
140 
141 /* Definition of the optional arguments in Language list */
142 static struct member_def language_members[] = {
143 	{ "Code ISO639"		},
144 	{ "Encoding"		},
145 	{ "Base Offset"		},
146 };
147 
148 /* Name of the various common attributes. See BT assigned numbers */
149 static struct attrib_def attrib_names[] = {
150 	{ 0x0, "ServiceRecordHandle", NULL, 0 },
151 	{ 0x1, "ServiceClassIDList", NULL, 0 },
152 	{ 0x2, "ServiceRecordState", NULL, 0 },
153 	{ 0x3, "ServiceID", NULL, 0 },
154 	{ 0x4, "ProtocolDescriptorList",
155 		protocol_members, sizeof(protocol_members)/sizeof(struct member_def) },
156 	{ 0x5, "BrowseGroupList", NULL, 0 },
157 	{ 0x6, "LanguageBaseAttributeIDList",
158 		language_members, sizeof(language_members)/sizeof(struct member_def) },
159 	{ 0x7, "ServiceInfoTimeToLive", NULL, 0 },
160 	{ 0x8, "ServiceAvailability", NULL, 0 },
161 	{ 0x9, "BluetoothProfileDescriptorList",
162 		profile_members, sizeof(profile_members)/sizeof(struct member_def) },
163 	{ 0xA, "DocumentationURL", NULL, 0 },
164 	{ 0xB, "ClientExecutableURL", NULL, 0 },
165 	{ 0xC, "IconURL", NULL, 0 },
166 	{ 0xD, "AdditionalProtocolDescriptorLists", NULL, 0 },
167 	/* Definitions after that are tricky (per profile or offset) */
168 };
169 
170 const int attrib_max = sizeof(attrib_names)/sizeof(struct attrib_def);
171 
172 /* Name of the various SPD attributes. See BT assigned numbers */
173 static struct attrib_def sdp_attrib_names[] = {
174 	{ 0x200, "VersionNumberList", NULL, 0 },
175 	{ 0x201, "ServiceDatabaseState", NULL, 0 },
176 };
177 
178 /* Name of the various SPD attributes. See BT assigned numbers */
179 static struct attrib_def browse_attrib_names[] = {
180 	{ 0x200, "GroupID", NULL, 0 },
181 };
182 
183 /* Name of the various Device ID attributes. See Device Id spec. */
184 static struct attrib_def did_attrib_names[] = {
185 	{ 0x200, "SpecificationID", NULL, 0 },
186 	{ 0x201, "VendorID", NULL, 0 },
187 	{ 0x202, "ProductID", NULL, 0 },
188 	{ 0x203, "Version", NULL, 0 },
189 	{ 0x204, "PrimaryRecord", NULL, 0 },
190 	{ 0x205, "VendorIDSource", NULL, 0 },
191 };
192 
193 /* Name of the various HID attributes. See HID spec. */
194 static struct attrib_def hid_attrib_names[] = {
195 	{ 0x200, "DeviceReleaseNum", NULL, 0 },
196 	{ 0x201, "ParserVersion", NULL, 0 },
197 	{ 0x202, "DeviceSubclass", NULL, 0 },
198 	{ 0x203, "CountryCode", NULL, 0 },
199 	{ 0x204, "VirtualCable", NULL, 0 },
200 	{ 0x205, "ReconnectInitiate", NULL, 0 },
201 	{ 0x206, "DescriptorList", NULL, 0 },
202 	{ 0x207, "LangIDBaseList", NULL, 0 },
203 	{ 0x208, "SDPDisable", NULL, 0 },
204 	{ 0x209, "BatteryPower", NULL, 0 },
205 	{ 0x20a, "RemoteWakeup", NULL, 0 },
206 	{ 0x20b, "ProfileVersion", NULL, 0 },
207 	{ 0x20c, "SupervisionTimeout", NULL, 0 },
208 	{ 0x20d, "NormallyConnectable", NULL, 0 },
209 	{ 0x20e, "BootDevice", NULL, 0 },
210 };
211 
212 /* Name of the various PAN attributes. See BT assigned numbers */
213 /* Note : those need to be double checked - Jean II */
214 static struct attrib_def pan_attrib_names[] = {
215 	{ 0x200, "IpSubnet", NULL, 0 },		/* Obsolete ??? */
216 	{ 0x30A, "SecurityDescription", NULL, 0 },
217 	{ 0x30B, "NetAccessType", NULL, 0 },
218 	{ 0x30C, "MaxNetAccessrate", NULL, 0 },
219 	{ 0x30D, "IPv4Subnet", NULL, 0 },
220 	{ 0x30E, "IPv6Subnet", NULL, 0 },
221 };
222 
223 /* Name of the various Generic-Audio attributes. See BT assigned numbers */
224 /* Note : totally untested - Jean II */
225 static struct attrib_def audio_attrib_names[] = {
226 	{ 0x302, "Remote audio volume control", NULL, 0 },
227 };
228 
229 /* Same for the UUIDs. See BT assigned numbers */
230 static struct uuid_def uuid16_names[] = {
231 	/* -- Protocols -- */
232 	{ 0x0001, "SDP", NULL, 0 },
233 	{ 0x0002, "UDP", NULL, 0 },
234 	{ 0x0003, "RFCOMM", NULL, 0 },
235 	{ 0x0004, "TCP", NULL, 0 },
236 	{ 0x0005, "TCS-BIN", NULL, 0 },
237 	{ 0x0006, "TCS-AT", NULL, 0 },
238 	{ 0x0008, "OBEX", NULL, 0 },
239 	{ 0x0009, "IP", NULL, 0 },
240 	{ 0x000a, "FTP", NULL, 0 },
241 	{ 0x000c, "HTTP", NULL, 0 },
242 	{ 0x000e, "WSP", NULL, 0 },
243 	{ 0x000f, "BNEP", NULL, 0 },
244 	{ 0x0010, "UPnP/ESDP", NULL, 0 },
245 	{ 0x0011, "HIDP", NULL, 0 },
246 	{ 0x0012, "HardcopyControlChannel", NULL, 0 },
247 	{ 0x0014, "HardcopyDataChannel", NULL, 0 },
248 	{ 0x0016, "HardcopyNotification", NULL, 0 },
249 	{ 0x0017, "AVCTP", NULL, 0 },
250 	{ 0x0019, "AVDTP", NULL, 0 },
251 	{ 0x001b, "CMTP", NULL, 0 },
252 	{ 0x001d, "UDI_C-Plane", NULL, 0 },
253 	{ 0x0100, "L2CAP", NULL, 0 },
254 	/* -- Services -- */
255 	{ 0x1000, "ServiceDiscoveryServerServiceClassID",
256 		sdp_attrib_names, sizeof(sdp_attrib_names)/sizeof(struct attrib_def) },
257 	{ 0x1001, "BrowseGroupDescriptorServiceClassID",
258 		browse_attrib_names, sizeof(browse_attrib_names)/sizeof(struct attrib_def) },
259 	{ 0x1002, "PublicBrowseGroup", NULL, 0 },
260 	{ 0x1101, "SerialPort", NULL, 0 },
261 	{ 0x1102, "LANAccessUsingPPP", NULL, 0 },
262 	{ 0x1103, "DialupNetworking (DUN)", NULL, 0 },
263 	{ 0x1104, "IrMCSync", NULL, 0 },
264 	{ 0x1105, "OBEXObjectPush", NULL, 0 },
265 	{ 0x1106, "OBEXFileTransfer", NULL, 0 },
266 	{ 0x1107, "IrMCSyncCommand", NULL, 0 },
267 	{ 0x1108, "Headset",
268 		audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) },
269 	{ 0x1109, "CordlessTelephony", NULL, 0 },
270 	{ 0x110a, "AudioSource", NULL, 0 },
271 	{ 0x110b, "AudioSink", NULL, 0 },
272 	{ 0x110c, "RemoteControlTarget", NULL, 0 },
273 	{ 0x110d, "AdvancedAudio", NULL, 0 },
274 	{ 0x110e, "RemoteControl", NULL, 0 },
275 	{ 0x110f, "VideoConferencing", NULL, 0 },
276 	{ 0x1110, "Intercom", NULL, 0 },
277 	{ 0x1111, "Fax", NULL, 0 },
278 	{ 0x1112, "HeadsetAudioGateway", NULL, 0 },
279 	{ 0x1113, "WAP", NULL, 0 },
280 	{ 0x1114, "WAP Client", NULL, 0 },
281 	{ 0x1115, "PANU (PAN/BNEP)",
282 		pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },
283 	{ 0x1116, "NAP (PAN/BNEP)",
284 		pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },
285 	{ 0x1117, "GN (PAN/BNEP)",
286 		pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },
287 	{ 0x1118, "DirectPrinting (BPP)", NULL, 0 },
288 	{ 0x1119, "ReferencePrinting (BPP)", NULL, 0 },
289 	{ 0x111a, "Imaging (BIP)", NULL, 0 },
290 	{ 0x111b, "ImagingResponder (BIP)", NULL, 0 },
291 	{ 0x111c, "ImagingAutomaticArchive (BIP)", NULL, 0 },
292 	{ 0x111d, "ImagingReferencedObjects (BIP)", NULL, 0 },
293 	{ 0x111e, "Handsfree", NULL, 0 },
294 	{ 0x111f, "HandsfreeAudioGateway", NULL, 0 },
295 	{ 0x1120, "DirectPrintingReferenceObjectsService (BPP)", NULL, 0 },
296 	{ 0x1121, "ReflectedUI (BPP)", NULL, 0 },
297 	{ 0x1122, "BasicPrinting (BPP)", NULL, 0 },
298 	{ 0x1123, "PrintingStatus (BPP)", NULL, 0 },
299 	{ 0x1124, "HumanInterfaceDeviceService (HID)",
300 		hid_attrib_names, sizeof(hid_attrib_names)/sizeof(struct attrib_def) },
301 	{ 0x1125, "HardcopyCableReplacement (HCR)", NULL, 0 },
302 	{ 0x1126, "HCR_Print (HCR)", NULL, 0 },
303 	{ 0x1127, "HCR_Scan (HCR)", NULL, 0 },
304 	{ 0x1128, "Common ISDN Access (CIP)", NULL, 0 },
305 	{ 0x1129, "VideoConferencingGW (VCP)", NULL, 0 },
306 	{ 0x112a, "UDI-MT", NULL, 0 },
307 	{ 0x112b, "UDI-TA", NULL, 0 },
308 	{ 0x112c, "Audio/Video", NULL, 0 },
309 	{ 0x112d, "SIM Access (SAP)", NULL, 0 },
310 	{ 0x112e, "Phonebook Access (PBAP) - PCE", NULL, 0 },
311 	{ 0x112f, "Phonebook Access (PBAP) - PSE", NULL, 0 },
312 	{ 0x1130, "Phonebook Access (PBAP)", NULL, 0 },
313 	/* ... */
314 	{ 0x1200, "PnPInformation",
315 		did_attrib_names, sizeof(did_attrib_names)/sizeof(struct attrib_def) },
316 	{ 0x1201, "GenericNetworking", NULL, 0 },
317 	{ 0x1202, "GenericFileTransfer", NULL, 0 },
318 	{ 0x1203, "GenericAudio",
319 		audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) },
320 	{ 0x1204, "GenericTelephony", NULL, 0 },
321 	/* ... */
322 	{ 0x1303, "VideoSource", NULL, 0 },
323 	{ 0x1304, "VideoSink", NULL, 0 },
324 	{ 0x1305, "VideoDistribution", NULL, 0 },
325 	{ 0x1400, "HDP", NULL, 0 },
326 	{ 0x1401, "HDPSource", NULL, 0 },
327 	{ 0x1402, "HDPSink", NULL, 0 },
328 	{ 0x2112, "AppleAgent", NULL, 0 },
329 };
330 
331 static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def);
332 
333 static void sdp_data_printf(sdp_data_t *, struct attrib_context *, int);
334 
335 /*
336  * Parse a UUID.
337  * The BT assigned numbers only list UUID16, so I'm not sure the
338  * other types will ever get used...
339  */
sdp_uuid_printf(uuid_t * uuid,struct attrib_context * context,int indent)340 static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent)
341 {
342 	if (uuid) {
343 		if (uuid->type == SDP_UUID16) {
344 			uint16_t uuidNum = uuid->value.uuid16;
345 			struct uuid_def *uuidDef = NULL;
346 			int i;
347 
348 			for (i = 0; i < uuid16_max; i++)
349 				if (uuid16_names[i].num == uuidNum) {
350 					uuidDef = &uuid16_names[i];
351 					break;
352 				}
353 
354 			/* Check if it's the service attribute */
355 			if (context->attrib && context->attrib->num == SERVICE_ATTR) {
356 				/* We got the service ID !!! */
357 				context->service = uuidDef;
358 			}
359 
360 			if (uuidDef)
361 				printf("%.*sUUID16 : 0x%.4x - %s\n",
362 					indent, indent_spaces, uuidNum, uuidDef->name);
363 			else
364 				printf("%.*sUUID16 : 0x%.4x\n",
365 					indent, indent_spaces, uuidNum);
366 		} else if (uuid->type == SDP_UUID32) {
367 			struct uuid_def *uuidDef = NULL;
368 			int i;
369 
370 			if (!(uuid->value.uuid32 & 0xffff0000)) {
371 				uint16_t uuidNum = uuid->value.uuid32;
372 				for (i = 0; i < uuid16_max; i++)
373 					if (uuid16_names[i].num == uuidNum) {
374 						uuidDef = &uuid16_names[i];
375 						break;
376 					}
377 			}
378 
379 			if (uuidDef)
380 				printf("%.*sUUID32 : 0x%.8x - %s\n",
381 					indent, indent_spaces, uuid->value.uuid32, uuidDef->name);
382 			else
383 				printf("%.*sUUID32 : 0x%.8x\n",
384 					indent, indent_spaces, uuid->value.uuid32);
385 		} else if (uuid->type == SDP_UUID128) {
386 			unsigned int data0;
387 			unsigned short data1;
388 			unsigned short data2;
389 			unsigned short data3;
390 			unsigned int data4;
391 			unsigned short data5;
392 
393 			memcpy(&data0, &uuid->value.uuid128.data[0], 4);
394 			memcpy(&data1, &uuid->value.uuid128.data[4], 2);
395 			memcpy(&data2, &uuid->value.uuid128.data[6], 2);
396 			memcpy(&data3, &uuid->value.uuid128.data[8], 2);
397 			memcpy(&data4, &uuid->value.uuid128.data[10], 4);
398 			memcpy(&data5, &uuid->value.uuid128.data[14], 2);
399 
400 			printf("%.*sUUID128 : 0x%.8x-%.4x-%.4x-%.4x-%.8x-%.4x\n",
401 				indent, indent_spaces,
402 				ntohl(data0), ntohs(data1), ntohs(data2),
403 				ntohs(data3), ntohl(data4), ntohs(data5));
404 		} else
405 			printf("%.*sEnum type of UUID not set\n",
406 				indent, indent_spaces);
407 	} else
408 		printf("%.*sNull passed to print UUID\n",
409 				indent, indent_spaces);
410 }
411 
412 /*
413  * Parse a sequence of data elements (i.e. a list)
414  */
printf_dataseq(sdp_data_t * pData,struct attrib_context * context,int indent)415 static void printf_dataseq(sdp_data_t * pData, struct attrib_context *context, int indent)
416 {
417 	sdp_data_t *sdpdata = NULL;
418 
419 	sdpdata = pData;
420 	if (sdpdata) {
421 		context->member_index = 0;
422 		do {
423 			sdp_data_printf(sdpdata, context, indent + 2);
424 			sdpdata = sdpdata->next;
425 			context->member_index++;
426 		} while (sdpdata);
427 	} else {
428 		printf("%.*sBroken dataseq link\n", indent, indent_spaces);
429 	}
430 }
431 
432 /*
433  * Parse a single data element (either in the attribute or in a data
434  * sequence).
435  */
sdp_data_printf(sdp_data_t * sdpdata,struct attrib_context * context,int indent)436 static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent)
437 {
438 	char *member_name = NULL;
439 
440 	/* Find member name. Almost black magic ;-) */
441 	if (context && context->attrib && context->attrib->members &&
442 			context->member_index < context->attrib->member_max) {
443 		member_name = context->attrib->members[context->member_index].name;
444 	}
445 
446 	switch (sdpdata->dtd) {
447 	case SDP_DATA_NIL:
448 		printf("%.*sNil\n", indent, indent_spaces);
449 		break;
450 	case SDP_BOOL:
451 	case SDP_UINT8:
452 	case SDP_UINT16:
453 	case SDP_UINT32:
454 	case SDP_UINT64:
455 	case SDP_UINT128:
456 	case SDP_INT8:
457 	case SDP_INT16:
458 	case SDP_INT32:
459 	case SDP_INT64:
460 	case SDP_INT128:
461 		if (member_name) {
462 			printf("%.*s%s (Integer) : 0x%x\n",
463 				indent, indent_spaces, member_name, sdpdata->val.uint32);
464 		} else {
465 			printf("%.*sInteger : 0x%x\n", indent, indent_spaces,
466 				sdpdata->val.uint32);
467 		}
468 		break;
469 
470 	case SDP_UUID16:
471 	case SDP_UUID32:
472 	case SDP_UUID128:
473 		//printf("%.*sUUID\n", indent, indent_spaces);
474 		sdp_uuid_printf(&sdpdata->val.uuid, context, indent);
475 		break;
476 
477 	case SDP_TEXT_STR8:
478 	case SDP_TEXT_STR16:
479 	case SDP_TEXT_STR32:
480 		if (sdpdata->unitSize > (int) strlen(sdpdata->val.str)) {
481 			int i;
482 			printf("%.*sData :", indent, indent_spaces);
483 			for (i = 0; i < sdpdata->unitSize; i++)
484 				printf(" %02x", (unsigned char) sdpdata->val.str[i]);
485 			printf("\n");
486 		} else
487 			printf("%.*sText : \"%s\"\n", indent, indent_spaces, sdpdata->val.str);
488 		break;
489 	case SDP_URL_STR8:
490 	case SDP_URL_STR16:
491 	case SDP_URL_STR32:
492 		printf("%.*sURL : %s\n", indent, indent_spaces, sdpdata->val.str);
493 		break;
494 
495 	case SDP_SEQ8:
496 	case SDP_SEQ16:
497 	case SDP_SEQ32:
498 		printf("%.*sData Sequence\n", indent, indent_spaces);
499 		printf_dataseq(sdpdata->val.dataseq, context, indent);
500 		break;
501 
502 	case SDP_ALT8:
503 	case SDP_ALT16:
504 	case SDP_ALT32:
505 		printf("%.*sData Sequence Alternates\n", indent, indent_spaces);
506 		printf_dataseq(sdpdata->val.dataseq, context, indent);
507 		break;
508 	}
509 }
510 
511 /*
512  * Parse a single attribute.
513  */
print_tree_attr_func(void * value,void * userData)514 static 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  */
print_tree_attr(sdp_record_t * rec)564 static 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 
print_raw_data(sdp_data_t * data,int indent)572 static 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 
print_raw_attr_func(void * value,void * userData)719 static 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 
print_raw_attr(sdp_record_t * rec)743 static 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  */
set_attrib(sdp_session_t * sess,uint32_t handle,uint16_t attrib,char * value)755 static 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 
808 static struct option set_options[] = {
809 	{ "help",	0, 0, 'h' },
810 	{ 0, 0, 0, 0 }
811 };
812 
813 static 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  */
cmd_setattr(int argc,char ** argv)820 static 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  */
set_attribseq(sdp_session_t * session,uint32_t handle,uint16_t attrib,int argc,char ** argv)862 static 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 
946 static struct option seq_options[] = {
947 	{ "help",	0, 0, 'h' },
948 	{ 0, 0, 0, 0 }
949 };
950 
951 static 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  */
cmd_setseq(int argc,char ** argv)959 static 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 
print_service_class(void * value,void * userData)1000 static 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 
print_service_desc(void * value,void * user)1013 static 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 
print_lang_attr(void * value,void * user)1068 static 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 
print_access_protos(void * value,void * userData)1076 static 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 
print_profile_desc(void * value,void * userData)1082 static 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  */
print_service_attr(sdp_record_t * rec)1098 static 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  */
1132 typedef 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 
add_lang_attr(sdp_record_t * r)1144 static 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 
add_sp(sdp_session_t * session,svc_info_t * si)1158 static 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 
1219 end:
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 
add_dun(sdp_session_t * session,svc_info_t * si)1229 static 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 
1281 end:
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 
add_fax(sdp_session_t * session,svc_info_t * si)1291 static 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");
1341 end:
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 
add_lan(sdp_session_t * session,svc_info_t * si)1350 static 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 
1400 end:
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 
add_headset(sdp_session_t * session,svc_info_t * si)1410 static 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 
1462 end:
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 
add_headset_ag(sdp_session_t * session,svc_info_t * si)1472 static 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 
1528 end:
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 
add_handsfree(sdp_session_t * session,svc_info_t * si)1538 static 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 
1594 end:
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 
add_handsfree_ag(sdp_session_t * session,svc_info_t * si)1604 static 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 
1667 end:
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 
add_simaccess(sdp_session_t * session,svc_info_t * si)1677 static 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 
1733 end:
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 
add_opush(sdp_session_t * session,svc_info_t * si)1743 static 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 
1813 end:
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 
add_pbap(sdp_session_t * session,svc_info_t * si)1824 static 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 
1885 end:
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 
add_ftp(sdp_session_t * session,svc_info_t * si)1896 static 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 
1950 end:
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 
add_directprint(sdp_session_t * session,svc_info_t * si)1961 static 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 
2015 end:
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 
add_nap(sdp_session_t * session,svc_info_t * si)2026 static 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 
2092 end:
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 
add_gn(sdp_session_t * session,svc_info_t * si)2103 static 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 
2155 end:
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 
add_panu(sdp_session_t * session,svc_info_t * si)2166 static 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 
2221 end:
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 
add_hid_keyb(sdp_session_t * session,svc_info_t * si)2232 static 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 
add_hid_wiimote(sdp_session_t * session,svc_info_t * si)2395 static 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 
add_cip(sdp_session_t * session,svc_info_t * si)2566 static 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 
2619 end:
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 
add_ctp(sdp_session_t * session,svc_info_t * si)2629 static 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 
2679 end:
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 
add_a2source(sdp_session_t * session,svc_info_t * si)2689 static 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 
2741 done:
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 
add_a2sink(sdp_session_t * session,svc_info_t * si)2750 static 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 
2802 done:
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 
add_avrct(sdp_session_t * session,svc_info_t * si)2811 static 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 
2866 done:
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 
add_avrtg(sdp_session_t * session,svc_info_t * si)2875 static 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 
2930 done:
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 
add_udi_ue(sdp_session_t * session,svc_info_t * si)2939 static 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 
add_udi_te(sdp_session_t * session,svc_info_t * si)2980 static 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 
3021 static unsigned char sr1_uuid[] = {	0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0,
3022 					0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 };
3023 
add_sr1(sdp_session_t * session,svc_info_t * si)3024 static 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 
3053 static unsigned char syncmls_uuid[] = {	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
3054 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
3055 
3056 static unsigned char syncmlc_uuid[] = {	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
3057 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
3058 
add_syncml(sdp_session_t * session,svc_info_t * si)3059 static 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 
3101 static unsigned char async_uuid[] = {	0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62,
3102 					0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C };
3103 
add_activesync(sdp_session_t * session,svc_info_t * si)3104 static 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 
3143 static unsigned char hotsync_uuid[] = {	0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
3144 					0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
3145 
add_hotsync(sdp_session_t * session,svc_info_t * si)3146 static 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 
3185 static unsigned char palmos_uuid[] = {	0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51,
3186 					0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 };
3187 
add_palmos(sdp_session_t * session,svc_info_t * si)3188 static 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 
3215 static unsigned char nokid_uuid[] = {	0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00,
3216 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3217 
add_nokiaid(sdp_session_t * session,svc_info_t * si)3218 static 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 
3250 static unsigned char pcsuite_uuid[] = {	0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00,
3251 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3252 
add_pcsuite(sdp_session_t * session,svc_info_t * si)3253 static 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 
3292 static unsigned char nftp_uuid[] = {	0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00,
3293 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3294 
3295 static unsigned char nsyncml_uuid[] = {	0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x10, 0x00,
3296 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3297 
3298 static unsigned char ngage_uuid[] = {	0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00,
3299 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
3300 
3301 static unsigned char apple_uuid[] = {	0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90,
3302 					0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 };
3303 
add_apple(sdp_session_t * session,svc_info_t * si)3304 static 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 
add_isync(sdp_session_t * session,svc_info_t * si)3340 static 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 
add_semchla(sdp_session_t * session,svc_info_t * si)3383 static 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 
add_gatt(sdp_session_t * session,svc_info_t * si)3431 static 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 
3501 struct {
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 */
add_service(bdaddr_t * bdaddr,svc_info_t * si)3565 static 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 
3586 done:
3587 	free(si->name);
3588 	sdp_close(sess);
3589 
3590 	return ret;
3591 }
3592 
3593 static 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 
3602 static const char *add_help =
3603 	"Usage:\n"
3604 	"\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n";
3605 
cmd_add(int argc,char ** argv)3606 static 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 */
del_service(bdaddr_t * bdaddr,void * arg)3660 static 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 
3701 static struct option del_options[] = {
3702 	{ "help",	0, 0, 'h' },
3703 	{ 0, 0, 0, 0 }
3704 };
3705 
3706 static const char *del_help =
3707 	"Usage:\n"
3708 	"\tdel record_handle\n";
3709 
cmd_del(int argc,char ** argv)3710 static 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  */
inquiry(handler_t handler,void * arg)3736 static 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 
doprintf(void * data,const char * str)3752 static void doprintf(void *data, const char *str)
3753 {
3754 	printf("%s", str);
3755 }
3756 
3757 /*
3758  * Search for a specific SDP service
3759  */
do_search(bdaddr_t * bdaddr,struct search_context * context)3760 static 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 
3837 static 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 
3847 static 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  */
cmd_browse(int argc,char ** argv)3855 static 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 
3904 static 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 
3913 static 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  */
cmd_search(int argc,char ** argv)3926 static 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  */
get_service(bdaddr_t * bdaddr,struct search_context * context,int quite)4012 static 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 
4064 static 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 
4072 static const char *records_help =
4073 	"Usage:\n"
4074 	"\trecords [--tree] [--raw] [--xml] bdaddr\n";
4075 
4076 /*
4077  * Request possible SDP service records
4078  */
cmd_records(int argc,char ** argv)4079 static 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 
4129 done:
4130 	return 0;
4131 }
4132 
4133 static 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 
4142 static 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  */
cmd_get(int argc,char ** argv)4149 static 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 
4194 static 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 
usage(void)4210 static 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 
4237 static struct option main_options[] = {
4238 	{ "help",	0, 0, 'h' },
4239 	{ "device",	1, 0, 'i' },
4240 	{ 0, 0, 0, 0 }
4241 };
4242 
main(int argc,char * argv[])4243 int 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