16b5c5d0dSHasso Tepper /* $NetBSD: search.c,v 1.6 2007/11/06 21:35:52 plunky Exp $ */
26b5c5d0dSHasso Tepper
36b5c5d0dSHasso Tepper /*-
46b5c5d0dSHasso Tepper * Copyright (c) 2006 Itronix Inc.
56b5c5d0dSHasso Tepper * All rights reserved.
66b5c5d0dSHasso Tepper *
76b5c5d0dSHasso Tepper * Redistribution and use in source and binary forms, with or without
86b5c5d0dSHasso Tepper * modification, are permitted provided that the following conditions
96b5c5d0dSHasso Tepper * are met:
106b5c5d0dSHasso Tepper * 1. Redistributions of source code must retain the above copyright
116b5c5d0dSHasso Tepper * notice, this list of conditions and the following disclaimer.
126b5c5d0dSHasso Tepper * 2. Redistributions in binary form must reproduce the above copyright
136b5c5d0dSHasso Tepper * notice, this list of conditions and the following disclaimer in the
146b5c5d0dSHasso Tepper * documentation and/or other materials provided with the distribution.
156b5c5d0dSHasso Tepper * 3. The name of Itronix Inc. may not be used to endorse
166b5c5d0dSHasso Tepper * or promote products derived from this software without specific
176b5c5d0dSHasso Tepper * prior written permission.
186b5c5d0dSHasso Tepper *
196b5c5d0dSHasso Tepper * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
206b5c5d0dSHasso Tepper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216b5c5d0dSHasso Tepper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226b5c5d0dSHasso Tepper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
236b5c5d0dSHasso Tepper * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
246b5c5d0dSHasso Tepper * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
256b5c5d0dSHasso Tepper * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
266b5c5d0dSHasso Tepper * ON ANY THEORY OF LIABILITY, WHETHER IN
276b5c5d0dSHasso Tepper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286b5c5d0dSHasso Tepper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296b5c5d0dSHasso Tepper * POSSIBILITY OF SUCH DAMAGE.
306b5c5d0dSHasso Tepper */
316b5c5d0dSHasso Tepper /*
326b5c5d0dSHasso Tepper * search.c
336b5c5d0dSHasso Tepper *
346b5c5d0dSHasso Tepper * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
356b5c5d0dSHasso Tepper * All rights reserved.
366b5c5d0dSHasso Tepper *
376b5c5d0dSHasso Tepper * Redistribution and use in source and binary forms, with or without
386b5c5d0dSHasso Tepper * modification, are permitted provided that the following conditions
396b5c5d0dSHasso Tepper * are met:
406b5c5d0dSHasso Tepper * 1. Redistributions of source code must retain the above copyright
416b5c5d0dSHasso Tepper * notice, this list of conditions and the following disclaimer.
426b5c5d0dSHasso Tepper * 2. Redistributions in binary form must reproduce the above copyright
436b5c5d0dSHasso Tepper * notice, this list of conditions and the following disclaimer in the
446b5c5d0dSHasso Tepper * documentation and/or other materials provided with the distribution.
456b5c5d0dSHasso Tepper *
466b5c5d0dSHasso Tepper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
476b5c5d0dSHasso Tepper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
486b5c5d0dSHasso Tepper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
496b5c5d0dSHasso Tepper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
506b5c5d0dSHasso Tepper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
516b5c5d0dSHasso Tepper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
526b5c5d0dSHasso Tepper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
536b5c5d0dSHasso Tepper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
546b5c5d0dSHasso Tepper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
556b5c5d0dSHasso Tepper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
566b5c5d0dSHasso Tepper * SUCH DAMAGE.
576b5c5d0dSHasso Tepper *
586b5c5d0dSHasso Tepper * $Id: search.c,v 1.6 2007/11/06 21:35:52 plunky Exp $
596b5c5d0dSHasso Tepper * $FreeBSD: src/usr.sbin/bluetooth/sdpcontrol/search.c,v 1.4 2005/05/27 19:11:33 emax Exp $
606b5c5d0dSHasso Tepper */
616b5c5d0dSHasso Tepper
626b5c5d0dSHasso Tepper #include <netinet/in.h>
636b5c5d0dSHasso Tepper #include <bluetooth.h>
646b5c5d0dSHasso Tepper #include <err.h>
656b5c5d0dSHasso Tepper #include <errno.h>
666b5c5d0dSHasso Tepper #include <ctype.h>
676b5c5d0dSHasso Tepper #include <sdp.h>
686b5c5d0dSHasso Tepper #include <stdio.h>
696b5c5d0dSHasso Tepper #include <stdlib.h>
706b5c5d0dSHasso Tepper
716b5c5d0dSHasso Tepper #include "sdpquery.h"
726b5c5d0dSHasso Tepper
736b5c5d0dSHasso Tepper /* List of the attributes we are looking for */
746b5c5d0dSHasso Tepper static uint32_t attrs[] =
756b5c5d0dSHasso Tepper {
766b5c5d0dSHasso Tepper SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE,
776b5c5d0dSHasso Tepper SDP_ATTR_SERVICE_RECORD_HANDLE),
786b5c5d0dSHasso Tepper SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST,
796b5c5d0dSHasso Tepper SDP_ATTR_SERVICE_CLASS_ID_LIST),
806b5c5d0dSHasso Tepper SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
816b5c5d0dSHasso Tepper SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
826b5c5d0dSHasso Tepper SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
836b5c5d0dSHasso Tepper SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST)
846b5c5d0dSHasso Tepper };
856b5c5d0dSHasso Tepper #define attrs_len (sizeof(attrs)/sizeof(attrs[0]))
866b5c5d0dSHasso Tepper
876b5c5d0dSHasso Tepper /* Buffer for the attributes */
886b5c5d0dSHasso Tepper #define NRECS 25 /* request this much records from the SDP server */
896b5c5d0dSHasso Tepper #define BSIZE 256 /* one attribute buffer size */
906b5c5d0dSHasso Tepper static uint8_t buffer[NRECS * attrs_len][BSIZE];
916b5c5d0dSHasso Tepper
926b5c5d0dSHasso Tepper /* SDP attributes */
936b5c5d0dSHasso Tepper static sdp_attr_t values[NRECS * attrs_len];
946b5c5d0dSHasso Tepper #define values_len (sizeof(values)/sizeof(values[0]))
956b5c5d0dSHasso Tepper
966b5c5d0dSHasso Tepper /*
976b5c5d0dSHasso Tepper * Print Service Class ID List
986b5c5d0dSHasso Tepper *
996b5c5d0dSHasso Tepper * The ServiceClassIDList attribute consists of a data element sequence in
1006b5c5d0dSHasso Tepper * which each data element is a UUID representing the service classes that
1016b5c5d0dSHasso Tepper * a given service record conforms to. The UUIDs are listed in order from
1026b5c5d0dSHasso Tepper * the most specific class to the most general class. The ServiceClassIDList
1036b5c5d0dSHasso Tepper * must contain at least one service class UUID.
1046b5c5d0dSHasso Tepper */
1056b5c5d0dSHasso Tepper
1066b5c5d0dSHasso Tepper static void
print_service_class_id_list(uint8_t const * start,uint8_t const * end)1076b5c5d0dSHasso Tepper print_service_class_id_list(uint8_t const *start, uint8_t const *end)
1086b5c5d0dSHasso Tepper {
1096b5c5d0dSHasso Tepper uint32_t type, len, value;
1106b5c5d0dSHasso Tepper
1116b5c5d0dSHasso Tepper if (end - start < 2) {
1126b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Service Class ID List. " \
113*9317c2d0SSascha Wildner "Too short, len=%td\n", end - start);
1146b5c5d0dSHasso Tepper return;
1156b5c5d0dSHasso Tepper }
1166b5c5d0dSHasso Tepper
1176b5c5d0dSHasso Tepper SDP_GET8(type, start);
1186b5c5d0dSHasso Tepper switch (type) {
1196b5c5d0dSHasso Tepper case SDP_DATA_SEQ8:
1206b5c5d0dSHasso Tepper SDP_GET8(len, start);
1216b5c5d0dSHasso Tepper break;
1226b5c5d0dSHasso Tepper
1236b5c5d0dSHasso Tepper case SDP_DATA_SEQ16:
1246b5c5d0dSHasso Tepper SDP_GET16(len, start);
1256b5c5d0dSHasso Tepper break;
1266b5c5d0dSHasso Tepper
1276b5c5d0dSHasso Tepper case SDP_DATA_SEQ32:
1286b5c5d0dSHasso Tepper SDP_GET32(len, start);
1296b5c5d0dSHasso Tepper break;
1306b5c5d0dSHasso Tepper
1316b5c5d0dSHasso Tepper default:
1326b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Service Class ID List. " \
1336b5c5d0dSHasso Tepper "Not a sequence, type=%#x\n", type);
1346b5c5d0dSHasso Tepper return;
1356b5c5d0dSHasso Tepper /* NOT REACHED */
1366b5c5d0dSHasso Tepper }
1376b5c5d0dSHasso Tepper
1386b5c5d0dSHasso Tepper while (start < end) {
1396b5c5d0dSHasso Tepper SDP_GET8(type, start);
1406b5c5d0dSHasso Tepper switch (type) {
1416b5c5d0dSHasso Tepper case SDP_DATA_UUID16:
1426b5c5d0dSHasso Tepper SDP_GET16(value, start);
1436b5c5d0dSHasso Tepper fprintf(stdout, "\t%s (%#4.4x)\n",
1446b5c5d0dSHasso Tepper sdp_uuid2desc(value), value);
1456b5c5d0dSHasso Tepper break;
1466b5c5d0dSHasso Tepper
1476b5c5d0dSHasso Tepper case SDP_DATA_UUID32:
1486b5c5d0dSHasso Tepper SDP_GET32(value, start);
1496b5c5d0dSHasso Tepper fprintf(stdout, "\t%#8.8x\n", value);
1506b5c5d0dSHasso Tepper break;
1516b5c5d0dSHasso Tepper
1526b5c5d0dSHasso Tepper case SDP_DATA_UUID128: {
1536b5c5d0dSHasso Tepper int128_t uuid;
1546b5c5d0dSHasso Tepper
1556b5c5d0dSHasso Tepper SDP_GET_UUID128(&uuid, start);
1566b5c5d0dSHasso Tepper fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
1576b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&uuid.b[0]),
1586b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[4]),
1596b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[6]),
1606b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[8]),
1616b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[10]),
1626b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&uuid.b[12]));
1636b5c5d0dSHasso Tepper } break;
1646b5c5d0dSHasso Tepper
1656b5c5d0dSHasso Tepper default:
1666b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Service Class ID List. " \
1676b5c5d0dSHasso Tepper "Not a UUID, type=%#x\n", type);
1686b5c5d0dSHasso Tepper return;
1696b5c5d0dSHasso Tepper /* NOT REACHED */
1706b5c5d0dSHasso Tepper }
1716b5c5d0dSHasso Tepper }
1726b5c5d0dSHasso Tepper } /* print_service_class_id_list */
1736b5c5d0dSHasso Tepper
1746b5c5d0dSHasso Tepper /*
1756b5c5d0dSHasso Tepper * Print Protocol Descriptor List
1766b5c5d0dSHasso Tepper *
1776b5c5d0dSHasso Tepper * If the ProtocolDescriptorList describes a single stack, it takes the form
1786b5c5d0dSHasso Tepper * of a data element sequence in which each element of the sequence is a
1796b5c5d0dSHasso Tepper * protocol descriptor. Each protocol descriptor is, in turn, a data element
1806b5c5d0dSHasso Tepper * sequence whose first element is a UUID identifying the protocol and whose
1816b5c5d0dSHasso Tepper * successive elements are protocol-specific parameters. The protocol
1826b5c5d0dSHasso Tepper * descriptors are listed in order from the lowest layer protocol to the
1836b5c5d0dSHasso Tepper * highest layer protocol used to gain access to the service. If it is possible
1846b5c5d0dSHasso Tepper * for more than one kind of protocol stack to be used to gain access to the
1856b5c5d0dSHasso Tepper * service, the ProtocolDescriptorList takes the form of a data element
1866b5c5d0dSHasso Tepper * alternative where each member is a data element sequence as described above.
1876b5c5d0dSHasso Tepper */
1886b5c5d0dSHasso Tepper
1896b5c5d0dSHasso Tepper static void
print_protocol_descriptor(uint8_t const * start,uint8_t const * end)1906b5c5d0dSHasso Tepper print_protocol_descriptor(uint8_t const *start, uint8_t const *end)
1916b5c5d0dSHasso Tepper {
1926b5c5d0dSHasso Tepper union {
1936b5c5d0dSHasso Tepper uint8_t uint8;
1946b5c5d0dSHasso Tepper uint16_t uint16;
1956b5c5d0dSHasso Tepper uint32_t uint32;
1966b5c5d0dSHasso Tepper uint64_t uint64;
1976b5c5d0dSHasso Tepper int128_t int128;
1986b5c5d0dSHasso Tepper } value;
1996b5c5d0dSHasso Tepper uint32_t type, len, param;
2006b5c5d0dSHasso Tepper
2016b5c5d0dSHasso Tepper /* Get Protocol UUID */
2026b5c5d0dSHasso Tepper SDP_GET8(type, start);
2036b5c5d0dSHasso Tepper switch (type) {
2046b5c5d0dSHasso Tepper case SDP_DATA_UUID16:
2056b5c5d0dSHasso Tepper SDP_GET16(value.uint16, start);
2066b5c5d0dSHasso Tepper fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16),
2076b5c5d0dSHasso Tepper value.uint16);
2086b5c5d0dSHasso Tepper break;
2096b5c5d0dSHasso Tepper
2106b5c5d0dSHasso Tepper case SDP_DATA_UUID32:
2116b5c5d0dSHasso Tepper SDP_GET32(value.uint32, start);
2126b5c5d0dSHasso Tepper fprintf(stdout, "\t%#8.8x\n", value.uint32);
2136b5c5d0dSHasso Tepper break;
2146b5c5d0dSHasso Tepper
2156b5c5d0dSHasso Tepper case SDP_DATA_UUID128:
2166b5c5d0dSHasso Tepper SDP_GET_UUID128(&value.int128, start);
2176b5c5d0dSHasso Tepper fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
2186b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&value.int128.b[0]),
2196b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[4]),
2206b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[6]),
2216b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[8]),
2226b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[10]),
2236b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&value.int128.b[12]));
2246b5c5d0dSHasso Tepper break;
2256b5c5d0dSHasso Tepper
2266b5c5d0dSHasso Tepper default:
2276b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Protocol Descriptor. " \
2286b5c5d0dSHasso Tepper "Not a UUID, type=%#x\n", type);
2296b5c5d0dSHasso Tepper return;
2306b5c5d0dSHasso Tepper /* NOT REACHED */
2316b5c5d0dSHasso Tepper }
2326b5c5d0dSHasso Tepper
2336b5c5d0dSHasso Tepper /* Protocol specific parameters */
2346b5c5d0dSHasso Tepper for (param = 1; start < end; param ++) {
2356b5c5d0dSHasso Tepper fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param);
2366b5c5d0dSHasso Tepper
2376b5c5d0dSHasso Tepper SDP_GET8(type, start);
2386b5c5d0dSHasso Tepper switch (type) {
2396b5c5d0dSHasso Tepper case SDP_DATA_NIL:
2406b5c5d0dSHasso Tepper fprintf(stdout, "nil\n");
2416b5c5d0dSHasso Tepper break;
2426b5c5d0dSHasso Tepper
2436b5c5d0dSHasso Tepper case SDP_DATA_UINT8:
2446b5c5d0dSHasso Tepper case SDP_DATA_INT8:
2456b5c5d0dSHasso Tepper case SDP_DATA_BOOL:
2466b5c5d0dSHasso Tepper SDP_GET8(value.uint8, start);
2476b5c5d0dSHasso Tepper fprintf(stdout, "u/int8/bool %u\n", value.uint8);
2486b5c5d0dSHasso Tepper break;
2496b5c5d0dSHasso Tepper
2506b5c5d0dSHasso Tepper case SDP_DATA_UINT16:
2516b5c5d0dSHasso Tepper case SDP_DATA_INT16:
2526b5c5d0dSHasso Tepper case SDP_DATA_UUID16:
2536b5c5d0dSHasso Tepper SDP_GET16(value.uint16, start);
2546b5c5d0dSHasso Tepper fprintf(stdout, "u/int/uuid16 %u\n", value.uint16);
2556b5c5d0dSHasso Tepper break;
2566b5c5d0dSHasso Tepper
2576b5c5d0dSHasso Tepper case SDP_DATA_UINT32:
2586b5c5d0dSHasso Tepper case SDP_DATA_INT32:
2596b5c5d0dSHasso Tepper case SDP_DATA_UUID32:
2606b5c5d0dSHasso Tepper SDP_GET32(value.uint32, start);
2616b5c5d0dSHasso Tepper fprintf(stdout, "u/int/uuid32 %u\n", value.uint32);
2626b5c5d0dSHasso Tepper break;
2636b5c5d0dSHasso Tepper
2646b5c5d0dSHasso Tepper case SDP_DATA_UINT64:
2656b5c5d0dSHasso Tepper case SDP_DATA_INT64:
2666b5c5d0dSHasso Tepper SDP_GET64(value.uint64, start);
2676b5c5d0dSHasso Tepper fprintf(stdout, "u/int64 %ju\n", value.uint64);
2686b5c5d0dSHasso Tepper break;
2696b5c5d0dSHasso Tepper
2706b5c5d0dSHasso Tepper case SDP_DATA_UINT128:
2716b5c5d0dSHasso Tepper case SDP_DATA_INT128:
2726b5c5d0dSHasso Tepper SDP_GET128(&value.int128, start);
2736b5c5d0dSHasso Tepper fprintf(stdout, "u/int128 %#8.8x%8.8x%8.8x%8.8x\n",
2746b5c5d0dSHasso Tepper *(uint32_t *)&value.int128.b[0],
2756b5c5d0dSHasso Tepper *(uint32_t *)&value.int128.b[4],
2766b5c5d0dSHasso Tepper *(uint32_t *)&value.int128.b[8],
2776b5c5d0dSHasso Tepper *(uint32_t *)&value.int128.b[12]);
2786b5c5d0dSHasso Tepper break;
2796b5c5d0dSHasso Tepper
2806b5c5d0dSHasso Tepper case SDP_DATA_UUID128:
2816b5c5d0dSHasso Tepper SDP_GET_UUID128(&value.int128, start);
2826b5c5d0dSHasso Tepper fprintf(stdout, "uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
2836b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&value.int128.b[0]),
2846b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[4]),
2856b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[6]),
2866b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[8]),
2876b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&value.int128.b[10]),
2886b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&value.int128.b[12]));
2896b5c5d0dSHasso Tepper break;
2906b5c5d0dSHasso Tepper
2916b5c5d0dSHasso Tepper case SDP_DATA_STR8:
2926b5c5d0dSHasso Tepper case SDP_DATA_URL8:
2936b5c5d0dSHasso Tepper SDP_GET8(len, start);
2946b5c5d0dSHasso Tepper fprintf(stdout, "%*.*s\n", len, len, start);
2956b5c5d0dSHasso Tepper start += len;
2966b5c5d0dSHasso Tepper break;
2976b5c5d0dSHasso Tepper
2986b5c5d0dSHasso Tepper case SDP_DATA_STR16:
2996b5c5d0dSHasso Tepper case SDP_DATA_URL16:
3006b5c5d0dSHasso Tepper SDP_GET16(len, start);
3016b5c5d0dSHasso Tepper fprintf(stdout, "%*.*s\n", len, len, start);
3026b5c5d0dSHasso Tepper start += len;
3036b5c5d0dSHasso Tepper break;
3046b5c5d0dSHasso Tepper
3056b5c5d0dSHasso Tepper case SDP_DATA_STR32:
3066b5c5d0dSHasso Tepper case SDP_DATA_URL32:
3076b5c5d0dSHasso Tepper SDP_GET32(len, start);
3086b5c5d0dSHasso Tepper fprintf(stdout, "%*.*s\n", len, len, start);
3096b5c5d0dSHasso Tepper start += len;
3106b5c5d0dSHasso Tepper break;
3116b5c5d0dSHasso Tepper
3126b5c5d0dSHasso Tepper case SDP_DATA_SEQ8:
3136b5c5d0dSHasso Tepper case SDP_DATA_ALT8:
3146b5c5d0dSHasso Tepper SDP_GET8(len, start);
3156b5c5d0dSHasso Tepper for (; len > 0; start ++, len --)
3166b5c5d0dSHasso Tepper fprintf(stdout, "%#2.2x ", *start);
3176b5c5d0dSHasso Tepper fprintf(stdout, "\n");
3186b5c5d0dSHasso Tepper break;
3196b5c5d0dSHasso Tepper
3206b5c5d0dSHasso Tepper case SDP_DATA_SEQ16:
3216b5c5d0dSHasso Tepper case SDP_DATA_ALT16:
3226b5c5d0dSHasso Tepper SDP_GET16(len, start);
3236b5c5d0dSHasso Tepper for (; len > 0; start ++, len --)
3246b5c5d0dSHasso Tepper fprintf(stdout, "%#2.2x ", *start);
3256b5c5d0dSHasso Tepper fprintf(stdout, "\n");
3266b5c5d0dSHasso Tepper break;
3276b5c5d0dSHasso Tepper
3286b5c5d0dSHasso Tepper case SDP_DATA_SEQ32:
3296b5c5d0dSHasso Tepper case SDP_DATA_ALT32:
3306b5c5d0dSHasso Tepper SDP_GET32(len, start);
3316b5c5d0dSHasso Tepper for (; len > 0; start ++, len --)
3326b5c5d0dSHasso Tepper fprintf(stdout, "%#2.2x ", *start);
3336b5c5d0dSHasso Tepper fprintf(stdout, "\n");
3346b5c5d0dSHasso Tepper break;
3356b5c5d0dSHasso Tepper
3366b5c5d0dSHasso Tepper default:
3376b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Protocol Descriptor. " \
3386b5c5d0dSHasso Tepper "Unknown data type: %#02x\n", type);
3396b5c5d0dSHasso Tepper return;
3406b5c5d0dSHasso Tepper /* NOT REACHED */
3416b5c5d0dSHasso Tepper }
3426b5c5d0dSHasso Tepper }
3436b5c5d0dSHasso Tepper } /* print_protocol_descriptor */
3446b5c5d0dSHasso Tepper
3456b5c5d0dSHasso Tepper static void
print_protocol_descriptor_list(uint8_t const * start,uint8_t const * end)3466b5c5d0dSHasso Tepper print_protocol_descriptor_list(uint8_t const *start, uint8_t const *end)
3476b5c5d0dSHasso Tepper {
3486b5c5d0dSHasso Tepper uint32_t type, len;
3496b5c5d0dSHasso Tepper
3506b5c5d0dSHasso Tepper if (end - start < 2) {
3516b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Protocol Descriptor List. " \
352*9317c2d0SSascha Wildner "Too short, len=%td\n", end - start);
3536b5c5d0dSHasso Tepper return;
3546b5c5d0dSHasso Tepper }
3556b5c5d0dSHasso Tepper
3566b5c5d0dSHasso Tepper SDP_GET8(type, start);
3576b5c5d0dSHasso Tepper switch (type) {
3586b5c5d0dSHasso Tepper case SDP_DATA_SEQ8:
3596b5c5d0dSHasso Tepper SDP_GET8(len, start);
3606b5c5d0dSHasso Tepper break;
3616b5c5d0dSHasso Tepper
3626b5c5d0dSHasso Tepper case SDP_DATA_SEQ16:
3636b5c5d0dSHasso Tepper SDP_GET16(len, start);
3646b5c5d0dSHasso Tepper break;
3656b5c5d0dSHasso Tepper
3666b5c5d0dSHasso Tepper case SDP_DATA_SEQ32:
3676b5c5d0dSHasso Tepper SDP_GET32(len, start);
3686b5c5d0dSHasso Tepper break;
3696b5c5d0dSHasso Tepper
3706b5c5d0dSHasso Tepper default:
3716b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Protocol Descriptor List. " \
3726b5c5d0dSHasso Tepper "Not a sequence, type=%#x\n", type);
3736b5c5d0dSHasso Tepper return;
3746b5c5d0dSHasso Tepper /* NOT REACHED */
3756b5c5d0dSHasso Tepper }
3766b5c5d0dSHasso Tepper
3776b5c5d0dSHasso Tepper while (start < end) {
3786b5c5d0dSHasso Tepper SDP_GET8(type, start);
3796b5c5d0dSHasso Tepper switch (type) {
3806b5c5d0dSHasso Tepper case SDP_DATA_SEQ8:
3816b5c5d0dSHasso Tepper SDP_GET8(len, start);
3826b5c5d0dSHasso Tepper break;
3836b5c5d0dSHasso Tepper
3846b5c5d0dSHasso Tepper case SDP_DATA_SEQ16:
3856b5c5d0dSHasso Tepper SDP_GET16(len, start);
3866b5c5d0dSHasso Tepper break;
3876b5c5d0dSHasso Tepper
3886b5c5d0dSHasso Tepper case SDP_DATA_SEQ32:
3896b5c5d0dSHasso Tepper SDP_GET32(len, start);
3906b5c5d0dSHasso Tepper break;
3916b5c5d0dSHasso Tepper
3926b5c5d0dSHasso Tepper default:
3936b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Protocol Descriptor List. " \
3946b5c5d0dSHasso Tepper "Not a sequence, type=%#x\n", type);
3956b5c5d0dSHasso Tepper return;
3966b5c5d0dSHasso Tepper /* NOT REACHED */
3976b5c5d0dSHasso Tepper }
3986b5c5d0dSHasso Tepper
3996b5c5d0dSHasso Tepper print_protocol_descriptor(start, start + len);
4006b5c5d0dSHasso Tepper start += len;
4016b5c5d0dSHasso Tepper }
4026b5c5d0dSHasso Tepper } /* print_protocol_descriptor_list */
4036b5c5d0dSHasso Tepper
4046b5c5d0dSHasso Tepper /*
4056b5c5d0dSHasso Tepper * Print Bluetooth Profile Descriptor List
4066b5c5d0dSHasso Tepper *
4076b5c5d0dSHasso Tepper * The BluetoothProfileDescriptorList attribute consists of a data element
4086b5c5d0dSHasso Tepper * sequence in which each element is a profile descriptor that contains
4096b5c5d0dSHasso Tepper * information about a Bluetooth profile to which the service represented by
4106b5c5d0dSHasso Tepper * this service record conforms. Each profile descriptor is a data element
4116b5c5d0dSHasso Tepper * sequence whose first element is the UUID assigned to the profile and whose
4126b5c5d0dSHasso Tepper * second element is a 16-bit profile version number. Each version of a profile
4136b5c5d0dSHasso Tepper * is assigned a 16-bit unsigned integer profile version number, which consists
4146b5c5d0dSHasso Tepper * of two 8-bit fields. The higher-order 8 bits contain the major version
4156b5c5d0dSHasso Tepper * number field and the lower-order 8 bits contain the minor version number
4166b5c5d0dSHasso Tepper * field.
4176b5c5d0dSHasso Tepper */
4186b5c5d0dSHasso Tepper
4196b5c5d0dSHasso Tepper static void
print_bluetooth_profile_descriptor_list(uint8_t const * start,uint8_t const * end)4206b5c5d0dSHasso Tepper print_bluetooth_profile_descriptor_list(uint8_t const *start, uint8_t const *end)
4216b5c5d0dSHasso Tepper {
4226b5c5d0dSHasso Tepper uint32_t type, len, value;
4236b5c5d0dSHasso Tepper
4246b5c5d0dSHasso Tepper if (end - start < 2) {
4256b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \
426*9317c2d0SSascha Wildner "Too short, len=%td\n", end - start);
4276b5c5d0dSHasso Tepper return;
4286b5c5d0dSHasso Tepper }
4296b5c5d0dSHasso Tepper
4306b5c5d0dSHasso Tepper SDP_GET8(type, start);
4316b5c5d0dSHasso Tepper switch (type) {
4326b5c5d0dSHasso Tepper case SDP_DATA_SEQ8:
4336b5c5d0dSHasso Tepper SDP_GET8(len, start);
4346b5c5d0dSHasso Tepper break;
4356b5c5d0dSHasso Tepper
4366b5c5d0dSHasso Tepper case SDP_DATA_SEQ16:
4376b5c5d0dSHasso Tepper SDP_GET16(len, start);
4386b5c5d0dSHasso Tepper break;
4396b5c5d0dSHasso Tepper
4406b5c5d0dSHasso Tepper case SDP_DATA_SEQ32:
4416b5c5d0dSHasso Tepper SDP_GET32(len, start);
4426b5c5d0dSHasso Tepper break;
4436b5c5d0dSHasso Tepper
4446b5c5d0dSHasso Tepper default:
4456b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \
4466b5c5d0dSHasso Tepper "Not a sequence, type=%#x\n", type);
4476b5c5d0dSHasso Tepper return;
4486b5c5d0dSHasso Tepper /* NOT REACHED */
4496b5c5d0dSHasso Tepper }
4506b5c5d0dSHasso Tepper
4516b5c5d0dSHasso Tepper while (start < end) {
4526b5c5d0dSHasso Tepper SDP_GET8(type, start);
4536b5c5d0dSHasso Tepper switch (type) {
4546b5c5d0dSHasso Tepper case SDP_DATA_SEQ8:
4556b5c5d0dSHasso Tepper SDP_GET8(len, start);
4566b5c5d0dSHasso Tepper break;
4576b5c5d0dSHasso Tepper
4586b5c5d0dSHasso Tepper case SDP_DATA_SEQ16:
4596b5c5d0dSHasso Tepper SDP_GET16(len, start);
4606b5c5d0dSHasso Tepper break;
4616b5c5d0dSHasso Tepper
4626b5c5d0dSHasso Tepper case SDP_DATA_SEQ32:
4636b5c5d0dSHasso Tepper SDP_GET32(len, start);
4646b5c5d0dSHasso Tepper break;
4656b5c5d0dSHasso Tepper
4666b5c5d0dSHasso Tepper default:
4676b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Bluetooth Profile " \
4686b5c5d0dSHasso Tepper "Descriptor List. " \
4696b5c5d0dSHasso Tepper "Not a sequence, type=%#x\n", type);
4706b5c5d0dSHasso Tepper return;
4716b5c5d0dSHasso Tepper /* NOT REACHED */
4726b5c5d0dSHasso Tepper }
4736b5c5d0dSHasso Tepper
4746b5c5d0dSHasso Tepper /* Get UUID */
4756b5c5d0dSHasso Tepper SDP_GET8(type, start);
4766b5c5d0dSHasso Tepper switch (type) {
4776b5c5d0dSHasso Tepper case SDP_DATA_UUID16:
4786b5c5d0dSHasso Tepper SDP_GET16(value, start);
4796b5c5d0dSHasso Tepper fprintf(stdout, "\t%s (%#4.4x) ",
4806b5c5d0dSHasso Tepper sdp_uuid2desc(value), value);
4816b5c5d0dSHasso Tepper break;
4826b5c5d0dSHasso Tepper
4836b5c5d0dSHasso Tepper case SDP_DATA_UUID32:
4846b5c5d0dSHasso Tepper SDP_GET32(value, start);
4856b5c5d0dSHasso Tepper fprintf(stdout, "\t%#8.8x ", value);
4866b5c5d0dSHasso Tepper break;
4876b5c5d0dSHasso Tepper
4886b5c5d0dSHasso Tepper case SDP_DATA_UUID128: {
4896b5c5d0dSHasso Tepper int128_t uuid;
4906b5c5d0dSHasso Tepper
4916b5c5d0dSHasso Tepper SDP_GET_UUID128(&uuid, start);
4926b5c5d0dSHasso Tepper fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ",
4936b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&uuid.b[0]),
4946b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[4]),
4956b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[6]),
4966b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[8]),
4976b5c5d0dSHasso Tepper ntohs(*(uint16_t *)&uuid.b[10]),
4986b5c5d0dSHasso Tepper ntohl(*(uint32_t *)&uuid.b[12]));
4996b5c5d0dSHasso Tepper } break;
5006b5c5d0dSHasso Tepper
5016b5c5d0dSHasso Tepper default:
5026b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Bluetooth Profile " \
5036b5c5d0dSHasso Tepper "Descriptor List. " \
5046b5c5d0dSHasso Tepper "Not a UUID, type=%#x\n", type);
5056b5c5d0dSHasso Tepper return;
5066b5c5d0dSHasso Tepper /* NOT REACHED */
5076b5c5d0dSHasso Tepper }
5086b5c5d0dSHasso Tepper
5096b5c5d0dSHasso Tepper /* Get version */
5106b5c5d0dSHasso Tepper SDP_GET8(type, start);
5116b5c5d0dSHasso Tepper if (type != SDP_DATA_UINT16) {
5126b5c5d0dSHasso Tepper fprintf(stderr, "Invalid Bluetooth Profile " \
5136b5c5d0dSHasso Tepper "Descriptor List. " \
5146b5c5d0dSHasso Tepper "Invalid version type=%#x\n", type);
5156b5c5d0dSHasso Tepper return;
5166b5c5d0dSHasso Tepper }
5176b5c5d0dSHasso Tepper
5186b5c5d0dSHasso Tepper SDP_GET16(value, start);
5196b5c5d0dSHasso Tepper fprintf(stdout, "ver. %d.%d\n",
5206b5c5d0dSHasso Tepper (value >> 8) & 0xff, value & 0xff);
5216b5c5d0dSHasso Tepper }
5226b5c5d0dSHasso Tepper } /* print_bluetooth_profile_descriptor_list */
5236b5c5d0dSHasso Tepper
5246b5c5d0dSHasso Tepper struct service {
5256b5c5d0dSHasso Tepper const char *name;
5266b5c5d0dSHasso Tepper uint16_t class;
5276b5c5d0dSHasso Tepper const char *description;
5286b5c5d0dSHasso Tepper } services[] = {
5296b5c5d0dSHasso Tepper { "CIP", SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS,
5306b5c5d0dSHasso Tepper "Common ISDN Access" },
5316b5c5d0dSHasso Tepper { "CTP", SDP_SERVICE_CLASS_CORDLESS_TELEPHONY,
5326b5c5d0dSHasso Tepper "Cordless Telephony" },
5336b5c5d0dSHasso Tepper { "DUN", SDP_SERVICE_CLASS_DIALUP_NETWORKING,
5346b5c5d0dSHasso Tepper "Dial Up Networking" },
5356b5c5d0dSHasso Tepper { "FAX", SDP_SERVICE_CLASS_FAX,
5366b5c5d0dSHasso Tepper "Fax" },
5376b5c5d0dSHasso Tepper { "FTRN", SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER,
5386b5c5d0dSHasso Tepper "Obex File Transfer" },
5396b5c5d0dSHasso Tepper { "GN", SDP_SERVICE_CLASS_GN,
5406b5c5d0dSHasso Tepper "Group ad-hoc Network" },
5416b5c5d0dSHasso Tepper { "HID", SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE,
5426b5c5d0dSHasso Tepper "Human Interface Device" },
5436b5c5d0dSHasso Tepper { "HF", SDP_SERVICE_CLASS_HANDSFREE,
5446b5c5d0dSHasso Tepper "Handsfree" },
5456b5c5d0dSHasso Tepper { "HSET", SDP_SERVICE_CLASS_HEADSET,
5466b5c5d0dSHasso Tepper "Headset" },
5476b5c5d0dSHasso Tepper { "LAN", SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP,
5486b5c5d0dSHasso Tepper "Lan access using PPP" },
5496b5c5d0dSHasso Tepper { "NAP", SDP_SERVICE_CLASS_NAP,
5506b5c5d0dSHasso Tepper "Network Access Point" },
5516b5c5d0dSHasso Tepper { "OPUSH", SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH,
5526b5c5d0dSHasso Tepper "OBEX Object Push" },
5536b5c5d0dSHasso Tepper { "PANU", SDP_SERVICE_CLASS_PANU,
5546b5c5d0dSHasso Tepper "Personal Area Networking User" },
5556b5c5d0dSHasso Tepper { "SP", SDP_SERVICE_CLASS_SERIAL_PORT,
5566b5c5d0dSHasso Tepper "Serial Port" },
5576b5c5d0dSHasso Tepper { NULL, 0,
5586b5c5d0dSHasso Tepper NULL }
5596b5c5d0dSHasso Tepper };
5606b5c5d0dSHasso Tepper
5616b5c5d0dSHasso Tepper /* Perform SDP search command */
5626b5c5d0dSHasso Tepper int
do_sdp_search(bdaddr_t * laddr,bdaddr_t * raddr,int argc,char const ** argv)5636b5c5d0dSHasso Tepper do_sdp_search(bdaddr_t *laddr, bdaddr_t *raddr, int argc, char const **argv)
5646b5c5d0dSHasso Tepper {
5656b5c5d0dSHasso Tepper struct service *s;
5666b5c5d0dSHasso Tepper void *xs;
5676b5c5d0dSHasso Tepper char *ep;
568f104a420SSascha Wildner uint32_t n;
569f104a420SSascha Wildner int32_t type, value;
5706b5c5d0dSHasso Tepper uint16_t service;
5716b5c5d0dSHasso Tepper
5726b5c5d0dSHasso Tepper if (argc != 1)
5736b5c5d0dSHasso Tepper goto usage;
5746b5c5d0dSHasso Tepper
5756b5c5d0dSHasso Tepper service = strtoul(*argv, &ep, 16);
5766b5c5d0dSHasso Tepper if (*ep != 0) {
5776b5c5d0dSHasso Tepper for (s = services ; ; s++) {
5786b5c5d0dSHasso Tepper if (s->name == NULL)
5796b5c5d0dSHasso Tepper goto usage;
5806b5c5d0dSHasso Tepper
5816b5c5d0dSHasso Tepper if (strcasecmp(s->name, *argv) == 0)
5826b5c5d0dSHasso Tepper break;
5836b5c5d0dSHasso Tepper }
5846b5c5d0dSHasso Tepper service = s->class;
5856b5c5d0dSHasso Tepper }
5866b5c5d0dSHasso Tepper
5876b5c5d0dSHasso Tepper /* Initialize attribute values array */
5886b5c5d0dSHasso Tepper for (n = 0; n < values_len; n ++) {
5896b5c5d0dSHasso Tepper values[n].flags = SDP_ATTR_INVALID;
5906b5c5d0dSHasso Tepper values[n].attr = 0;
5916b5c5d0dSHasso Tepper values[n].vlen = BSIZE;
5926b5c5d0dSHasso Tepper values[n].value = buffer[n];
5936b5c5d0dSHasso Tepper }
5946b5c5d0dSHasso Tepper
5956b5c5d0dSHasso Tepper if (bdaddr_any(raddr))
5966b5c5d0dSHasso Tepper xs = sdp_open_local(control_socket);
5976b5c5d0dSHasso Tepper else
5986b5c5d0dSHasso Tepper xs = sdp_open(laddr, raddr);
5996b5c5d0dSHasso Tepper
6006b5c5d0dSHasso Tepper if (xs == NULL || (errno = sdp_error(xs)) != 0)
6016b5c5d0dSHasso Tepper err(EXIT_FAILURE, "sdp_open");
6026b5c5d0dSHasso Tepper
6036b5c5d0dSHasso Tepper /* Do SDP Service Search Attribute Request */
6046b5c5d0dSHasso Tepper n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values);
6056b5c5d0dSHasso Tepper if (n != 0)
6066b5c5d0dSHasso Tepper err(EXIT_FAILURE, "sdp_search");
6076b5c5d0dSHasso Tepper
6086b5c5d0dSHasso Tepper sdp_close(xs);
6096b5c5d0dSHasso Tepper
6106b5c5d0dSHasso Tepper /* Print attributes values */
6116b5c5d0dSHasso Tepper for (n = 0; n < values_len; n ++) {
6126b5c5d0dSHasso Tepper if (values[n].flags != SDP_ATTR_OK)
6136b5c5d0dSHasso Tepper break;
6146b5c5d0dSHasso Tepper
6156b5c5d0dSHasso Tepper switch (values[n].attr) {
6166b5c5d0dSHasso Tepper case SDP_ATTR_SERVICE_RECORD_HANDLE:
6176b5c5d0dSHasso Tepper fprintf(stdout, "\n");
6186b5c5d0dSHasso Tepper if (values[n].vlen == 5) {
6196b5c5d0dSHasso Tepper SDP_GET8(type, values[n].value);
6206b5c5d0dSHasso Tepper if (type == SDP_DATA_UINT32) {
6216b5c5d0dSHasso Tepper SDP_GET32(value, values[n].value);
6226b5c5d0dSHasso Tepper fprintf(stdout, "Record Handle: " \
6236b5c5d0dSHasso Tepper "%#8.8x\n", value);
6246b5c5d0dSHasso Tepper } else
6256b5c5d0dSHasso Tepper fprintf(stderr, "Invalid type=%#x " \
6266b5c5d0dSHasso Tepper "Record Handle " \
6276b5c5d0dSHasso Tepper "attribute!\n", type);
6286b5c5d0dSHasso Tepper } else
6296b5c5d0dSHasso Tepper fprintf(stderr, "Invalid size=%d for Record " \
6306b5c5d0dSHasso Tepper "Handle attribute\n",
6316b5c5d0dSHasso Tepper values[n].vlen);
6326b5c5d0dSHasso Tepper break;
6336b5c5d0dSHasso Tepper
6346b5c5d0dSHasso Tepper case SDP_ATTR_SERVICE_CLASS_ID_LIST:
6356b5c5d0dSHasso Tepper fprintf(stdout, "Service Class ID List:\n");
6366b5c5d0dSHasso Tepper print_service_class_id_list(values[n].value,
6376b5c5d0dSHasso Tepper values[n].value + values[n].vlen);
6386b5c5d0dSHasso Tepper break;
6396b5c5d0dSHasso Tepper
6406b5c5d0dSHasso Tepper case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
6416b5c5d0dSHasso Tepper fprintf(stdout, "Protocol Descriptor List:\n");
6426b5c5d0dSHasso Tepper print_protocol_descriptor_list(values[n].value,
6436b5c5d0dSHasso Tepper values[n].value + values[n].vlen);
6446b5c5d0dSHasso Tepper break;
6456b5c5d0dSHasso Tepper
6466b5c5d0dSHasso Tepper case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST:
6476b5c5d0dSHasso Tepper fprintf(stdout, "Bluetooth Profile Descriptor List:\n");
6486b5c5d0dSHasso Tepper print_bluetooth_profile_descriptor_list(values[n].value,
6496b5c5d0dSHasso Tepper values[n].value + values[n].vlen);
6506b5c5d0dSHasso Tepper break;
6516b5c5d0dSHasso Tepper
6526b5c5d0dSHasso Tepper default:
6536b5c5d0dSHasso Tepper fprintf(stderr, "Unexpected attribute ID=%#4.4x\n",
6546b5c5d0dSHasso Tepper values[n].attr);
6556b5c5d0dSHasso Tepper break;
6566b5c5d0dSHasso Tepper }
6576b5c5d0dSHasso Tepper }
6586b5c5d0dSHasso Tepper
6596b5c5d0dSHasso Tepper return EXIT_SUCCESS;
6606b5c5d0dSHasso Tepper
6616b5c5d0dSHasso Tepper usage:
6626b5c5d0dSHasso Tepper fprintf(stderr, "Known services:\n");
6636b5c5d0dSHasso Tepper for (s = services ; s->name != NULL ; s++)
6646b5c5d0dSHasso Tepper fprintf(stderr, "\t%s\t%s\n", s->name, s->description);
6656b5c5d0dSHasso Tepper
6666b5c5d0dSHasso Tepper return EXIT_FAILURE;
6676b5c5d0dSHasso Tepper } /* do_sdp_search */
6686b5c5d0dSHasso Tepper
6696b5c5d0dSHasso Tepper /* Perform SDP browse command */
6706b5c5d0dSHasso Tepper int
do_sdp_browse(bdaddr_t * laddr,bdaddr_t * raddr,int argc,char const ** argv)6716b5c5d0dSHasso Tepper do_sdp_browse(bdaddr_t *laddr, bdaddr_t *raddr, int argc, char const **argv)
6726b5c5d0dSHasso Tepper {
6736b5c5d0dSHasso Tepper #undef _STR
6746b5c5d0dSHasso Tepper #undef STR
6756b5c5d0dSHasso Tepper #define _STR(x) #x
6766b5c5d0dSHasso Tepper #define STR(x) _STR(x)
6776b5c5d0dSHasso Tepper
6786b5c5d0dSHasso Tepper static char const * av[] = {
6796b5c5d0dSHasso Tepper STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP),
6806b5c5d0dSHasso Tepper NULL
6816b5c5d0dSHasso Tepper };
6826b5c5d0dSHasso Tepper
6836b5c5d0dSHasso Tepper switch (argc) {
6846b5c5d0dSHasso Tepper case 0:
6856b5c5d0dSHasso Tepper argc = 1;
6866b5c5d0dSHasso Tepper argv = (char const **) av;
6876b5c5d0dSHasso Tepper /* FALL THROUGH */
6886b5c5d0dSHasso Tepper case 1:
6896b5c5d0dSHasso Tepper return (do_sdp_search(laddr, raddr, argc, argv));
6906b5c5d0dSHasso Tepper }
6916b5c5d0dSHasso Tepper
6926b5c5d0dSHasso Tepper return EXIT_FAILURE;
6936b5c5d0dSHasso Tepper } /* do_sdp_browse */
694