]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/bluetooth/sdpcontrol/search.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / bluetooth / sdpcontrol / search.c
1 /*
2  * search.c
3  *
4  * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $
29  * $FreeBSD$
30  */
31
32 #include <netinet/in.h>
33 #include <bluetooth.h>
34 #include <ctype.h>
35 #include <sdp.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include "sdpcontrol.h"
39
40 /* List of the attributes we are looking for */
41 static uint32_t attrs[] =
42 {
43         SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE,
44                         SDP_ATTR_SERVICE_RECORD_HANDLE),
45         SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST,
46                         SDP_ATTR_SERVICE_CLASS_ID_LIST),
47         SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
48                         SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
49         SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
50                         SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST)
51 };
52 #define attrs_len       (sizeof(attrs)/sizeof(attrs[0]))
53
54 /* Buffer for the attributes */
55 #define NRECS   25      /* request this much records from the SDP server */
56 #define BSIZE   256     /* one attribute buffer size */
57 static uint8_t          buffer[NRECS * attrs_len][BSIZE];
58
59 /* SDP attributes */
60 static sdp_attr_t       values[NRECS * attrs_len];
61 #define values_len      (sizeof(values)/sizeof(values[0]))
62
63 /*
64  * Print Service Class ID List
65  *
66  * The ServiceClassIDList attribute consists of a data element sequence in 
67  * which each data element is a UUID representing the service classes that
68  * a given service record conforms to. The UUIDs are listed in order from 
69  * the most specific class to the most general class. The ServiceClassIDList
70  * must contain at least one service class UUID.
71  */
72
73 static void
74 print_service_class_id_list(uint8_t const *start, uint8_t const *end)
75 {
76         uint32_t        type, len, value;
77
78         if (end - start < 2) {
79                 fprintf(stderr, "Invalid Service Class ID List. " \
80                                 "Too short, len=%zd\n", end - start);
81                 return;
82         }
83
84         SDP_GET8(type, start);
85         switch (type) {
86         case SDP_DATA_SEQ8:
87                 SDP_GET8(len, start);
88                 break;
89
90         case SDP_DATA_SEQ16:
91                 SDP_GET16(len, start);
92                 break;
93
94         case SDP_DATA_SEQ32:
95                 SDP_GET32(len, start);
96                 break;
97
98         default:
99                 fprintf(stderr, "Invalid Service Class ID List. " \
100                                 "Not a sequence, type=%#x\n", type);
101                 return;
102                 /* NOT REACHED */
103         }
104
105         while (start < end) {
106                 SDP_GET8(type, start);
107                 switch (type) {
108                 case SDP_DATA_UUID16:
109                         SDP_GET16(value, start);
110                         fprintf(stdout, "\t%s (%#4.4x)\n",
111                                         sdp_uuid2desc(value), value);
112                         break;
113
114                 case SDP_DATA_UUID32:
115                         SDP_GET32(value, start);
116                         fprintf(stdout, "\t%#8.8x\n", value);
117                         break;
118
119                 case SDP_DATA_UUID128: {
120                         int128_t        uuid;
121
122                         SDP_GET_UUID128(&uuid, start);
123                         fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
124                                         ntohl(*(uint32_t *)&uuid.b[0]),
125                                         ntohs(*(uint16_t *)&uuid.b[4]),
126                                         ntohs(*(uint16_t *)&uuid.b[6]),
127                                         ntohs(*(uint16_t *)&uuid.b[8]),
128                                         ntohs(*(uint16_t *)&uuid.b[10]),
129                                         ntohl(*(uint32_t *)&uuid.b[12]));
130                         } break;
131
132                 default:
133                         fprintf(stderr, "Invalid Service Class ID List. " \
134                                         "Not a UUID, type=%#x\n", type);
135                         return;
136                         /* NOT REACHED */
137                 }
138         }
139 } /* print_service_class_id_list */
140
141 /*
142  * Print Protocol Descriptor List
143  *
144  * If the ProtocolDescriptorList describes a single stack, it takes the form 
145  * of a data element sequence in which each element of the sequence is a 
146  * protocol descriptor. Each protocol descriptor is, in turn, a data element 
147  * sequence whose first element is a UUID identifying the protocol and whose 
148  * successive elements are protocol-specific parameters. The protocol 
149  * descriptors are listed in order from the lowest layer protocol to the 
150  * highest layer protocol used to gain access to the service. If it is possible
151  * for more than one kind of protocol stack to be used to gain access to the 
152  * service, the ProtocolDescriptorList takes the form of a data element 
153  * alternative where each member is a data element sequence as described above.
154  */
155
156 static void
157 print_protocol_descriptor(uint8_t const *start, uint8_t const *end)
158 {
159         union {
160                 uint8_t         uint8;
161                 uint16_t        uint16;
162                 uint32_t        uint32;
163                 uint64_t        uint64;
164                 int128_t        int128;
165         }                       value;
166         uint32_t                type, len, param;
167
168         /* Get Protocol UUID */
169         SDP_GET8(type, start);
170         switch (type) {
171         case SDP_DATA_UUID16:
172                 SDP_GET16(value.uint16, start);
173                 fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16),
174                                 value.uint16);
175                 break;
176
177         case SDP_DATA_UUID32:
178                 SDP_GET32(value.uint32, start);
179                 fprintf(stdout, "\t%#8.8x\n", value.uint32);
180                 break;
181
182         case SDP_DATA_UUID128:
183                 SDP_GET_UUID128(&value.int128, start);
184                 fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
185                                 ntohl(*(uint32_t *)&value.int128.b[0]),
186                                 ntohs(*(uint16_t *)&value.int128.b[4]),
187                                 ntohs(*(uint16_t *)&value.int128.b[6]),
188                                 ntohs(*(uint16_t *)&value.int128.b[8]),
189                                 ntohs(*(uint16_t *)&value.int128.b[10]),
190                                 ntohl(*(uint32_t *)&value.int128.b[12]));
191                 break;
192
193         default:
194                 fprintf(stderr, "Invalid Protocol Descriptor. " \
195                                 "Not a UUID, type=%#x\n", type);
196                 return;
197                 /* NOT REACHED */
198         }
199
200         /* Protocol specific parameters */
201         for (param = 1; start < end; param ++) {
202                 fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param);
203
204                 SDP_GET8(type, start);
205                 switch (type) {
206                 case SDP_DATA_NIL:
207                         fprintf(stdout, "nil\n");
208                         break;
209
210                 case SDP_DATA_UINT8:
211                 case SDP_DATA_INT8:
212                 case SDP_DATA_BOOL:
213                         SDP_GET8(value.uint8, start);
214                         fprintf(stdout, "u/int8/bool %u\n", value.uint8);
215                         break;
216
217                 case SDP_DATA_UINT16:
218                 case SDP_DATA_INT16:
219                 case SDP_DATA_UUID16:
220                         SDP_GET16(value.uint16, start);
221                         fprintf(stdout, "u/int/uuid16 %u\n", value.uint16);
222                         break;
223
224                 case SDP_DATA_UINT32:
225                 case SDP_DATA_INT32:
226                 case SDP_DATA_UUID32:
227                         SDP_GET32(value.uint32, start);
228                         fprintf(stdout, "u/int/uuid32 %u\n", value.uint32);
229                         break;
230
231                 case SDP_DATA_UINT64:
232                 case SDP_DATA_INT64:
233                         SDP_GET64(value.uint64, start);
234                         fprintf(stdout, "u/int64 %ju\n", value.uint64);
235                         break;
236
237                 case SDP_DATA_UINT128:
238                 case SDP_DATA_INT128:
239                         SDP_GET128(&value.int128, start);
240                         fprintf(stdout, "u/int128 %#8.8x%8.8x%8.8x%8.8x\n",
241                                 *(uint32_t *)&value.int128.b[0],
242                                 *(uint32_t *)&value.int128.b[4],
243                                 *(uint32_t *)&value.int128.b[8],
244                                 *(uint32_t *)&value.int128.b[12]);
245                         break;
246
247                 case SDP_DATA_UUID128:
248                         SDP_GET_UUID128(&value.int128, start);
249                         fprintf(stdout, "uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
250                                 ntohl(*(uint32_t *)&value.int128.b[0]),
251                                 ntohs(*(uint16_t *)&value.int128.b[4]),
252                                 ntohs(*(uint16_t *)&value.int128.b[6]),
253                                 ntohs(*(uint16_t *)&value.int128.b[8]),
254                                 ntohs(*(uint16_t *)&value.int128.b[10]),
255                                 ntohl(*(uint32_t *)&value.int128.b[12]));
256                         break;
257
258                 case SDP_DATA_STR8:
259                 case SDP_DATA_URL8:
260                         SDP_GET8(len, start);
261                         fprintf(stdout, "%*.*s\n", len, len, (char *) start);
262                         start += len;
263                         break;
264
265                 case SDP_DATA_STR16:
266                 case SDP_DATA_URL16:
267                         SDP_GET16(len, start);
268                         fprintf(stdout, "%*.*s\n", len, len, (char *) start);
269                         start += len;
270                         break;
271
272                 case SDP_DATA_STR32:
273                 case SDP_DATA_URL32:
274                         SDP_GET32(len, start);
275                         fprintf(stdout, "%*.*s\n", len, len, (char *) start);
276                         start += len;
277                         break;
278
279                 case SDP_DATA_SEQ8:
280                 case SDP_DATA_ALT8:
281                         SDP_GET8(len, start);
282                         for (; len > 0; start ++, len --)
283                                 fprintf(stdout, "%#2.2x ", *start);
284                         fprintf(stdout, "\n");
285                         break;
286
287                 case SDP_DATA_SEQ16:
288                 case SDP_DATA_ALT16:
289                         SDP_GET16(len, start);
290                         for (; len > 0; start ++, len --)
291                                 fprintf(stdout, "%#2.2x ", *start);
292                         fprintf(stdout, "\n");
293                         break;
294
295                 case SDP_DATA_SEQ32:
296                 case SDP_DATA_ALT32:
297                         SDP_GET32(len, start);
298                         for (; len > 0; start ++, len --)
299                                 fprintf(stdout, "%#2.2x ", *start);
300                         fprintf(stdout, "\n");
301                         break;
302
303                 default:
304                         fprintf(stderr, "Invalid Protocol Descriptor. " \
305                                         "Unknown data type: %#02x\n", type);
306                         return;
307                         /* NOT REACHED */
308                 }
309         }
310 } /* print_protocol_descriptor */
311
312 static void
313 print_protocol_descriptor_list(uint8_t const *start, uint8_t const *end)
314 {
315         uint32_t        type, len;
316
317         if (end - start < 2) {
318                 fprintf(stderr, "Invalid Protocol Descriptor List. " \
319                                 "Too short, len=%zd\n", end - start);
320                 return;
321         }
322
323         SDP_GET8(type, start);
324         switch (type) {
325         case SDP_DATA_SEQ8:
326                 SDP_GET8(len, start);
327                 break;
328
329         case SDP_DATA_SEQ16:
330                 SDP_GET16(len, start);
331                 break;
332
333         case SDP_DATA_SEQ32:
334                 SDP_GET32(len, start);
335                 break;
336
337         default:
338                 fprintf(stderr, "Invalid Protocol Descriptor List. " \
339                                 "Not a sequence, type=%#x\n", type);
340                 return;
341                 /* NOT REACHED */
342         }
343
344         while (start < end) {
345                 SDP_GET8(type, start);
346                 switch (type) {
347                 case SDP_DATA_SEQ8:
348                         SDP_GET8(len, start);
349                         break;
350
351                 case SDP_DATA_SEQ16:
352                         SDP_GET16(len, start);
353                         break;
354
355                 case SDP_DATA_SEQ32:
356                         SDP_GET32(len, start);
357                         break;
358
359                 default:
360                         fprintf(stderr, "Invalid Protocol Descriptor List. " \
361                                         "Not a sequence, type=%#x\n", type);
362                         return;
363                         /* NOT REACHED */
364                 }
365
366                 print_protocol_descriptor(start, start + len);
367                 start += len;
368         }
369 } /* print_protocol_descriptor_list */
370
371 /*
372  * Print Bluetooth Profile Descriptor List
373  *
374  * The BluetoothProfileDescriptorList attribute consists of a data element 
375  * sequence in which each element is a profile descriptor that contains 
376  * information about a Bluetooth profile to which the service represented by 
377  * this service record conforms. Each profile descriptor is a data element 
378  * sequence whose first element is the UUID assigned to the profile and whose 
379  * second element is a 16-bit profile version number. Each version of a profile
380  * is assigned a 16-bit unsigned integer profile version number, which consists
381  * of two 8-bit fields. The higher-order 8 bits contain the major version 
382  * number field and the lower-order 8 bits contain the minor version number 
383  * field.
384  */
385
386 static void
387 print_bluetooth_profile_descriptor_list(uint8_t const *start, uint8_t const *end)
388 {
389         uint32_t        type, len, value;
390
391         if (end - start < 2) {
392                 fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \
393                                 "Too short, len=%zd\n", end - start);
394                 return;
395         }
396
397         SDP_GET8(type, start);
398         switch (type) {
399         case SDP_DATA_SEQ8:
400                 SDP_GET8(len, start);
401                 break;
402
403         case SDP_DATA_SEQ16:
404                 SDP_GET16(len, start);
405                 break;
406
407         case SDP_DATA_SEQ32:
408                 SDP_GET32(len, start);
409                 break;
410
411         default:
412                 fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \
413                                 "Not a sequence, type=%#x\n", type);
414                 return;
415                 /* NOT REACHED */
416         }
417
418         while (start < end) {
419                 SDP_GET8(type, start);
420                 switch (type) {
421                 case SDP_DATA_SEQ8:
422                         SDP_GET8(len, start);
423                         break;
424
425                 case SDP_DATA_SEQ16:
426                         SDP_GET16(len, start);
427                         break;
428
429                 case SDP_DATA_SEQ32:
430                         SDP_GET32(len, start);
431                         break;
432
433                 default:
434                         fprintf(stderr, "Invalid Bluetooth Profile " \
435                                         "Descriptor List. " \
436                                         "Not a sequence, type=%#x\n", type);
437                         return;
438                         /* NOT REACHED */
439                 }
440
441                 /* Get UUID */
442                 SDP_GET8(type, start);
443                 switch (type) {
444                 case SDP_DATA_UUID16:
445                         SDP_GET16(value, start);
446                         fprintf(stdout, "\t%s (%#4.4x) ",
447                                         sdp_uuid2desc(value), value);
448                         break;
449
450                 case SDP_DATA_UUID32:
451                         SDP_GET32(value, start);
452                         fprintf(stdout, "\t%#8.8x ", value);
453                         break;
454
455                 case SDP_DATA_UUID128: {
456                         int128_t        uuid;
457
458                         SDP_GET_UUID128(&uuid, start);
459                         fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ",
460                                         ntohl(*(uint32_t *)&uuid.b[0]),
461                                         ntohs(*(uint16_t *)&uuid.b[4]),
462                                         ntohs(*(uint16_t *)&uuid.b[6]),
463                                         ntohs(*(uint16_t *)&uuid.b[8]),
464                                         ntohs(*(uint16_t *)&uuid.b[10]),
465                                         ntohl(*(uint32_t *)&uuid.b[12]));
466                         } break;
467
468                 default:
469                         fprintf(stderr, "Invalid Bluetooth Profile " \
470                                         "Descriptor List. " \
471                                         "Not a UUID, type=%#x\n", type);
472                         return;
473                         /* NOT REACHED */
474                 }
475
476                 /* Get version */
477                 SDP_GET8(type, start);
478                 if (type != SDP_DATA_UINT16) {
479                         fprintf(stderr, "Invalid Bluetooth Profile " \
480                                         "Descriptor List. " \
481                                         "Invalid version type=%#x\n", type);
482                         return;
483                 }
484
485                 SDP_GET16(value, start);
486                 fprintf(stdout, "ver. %d.%d\n",
487                                 (value >> 8) & 0xff, value & 0xff);
488         }
489 } /* print_bluetooth_profile_descriptor_list */
490
491 /* Perform SDP search command */
492 static int
493 do_sdp_search(void *xs, int argc, char **argv)
494 {
495         char            *ep = NULL;
496         int32_t          n, type, value;
497         uint16_t         service;
498
499         /* Parse command line arguments */
500         switch (argc) {
501         case 1:
502                 n = strtoul(argv[0], &ep, 16);
503                 if (*ep != 0) {
504                         switch (tolower(argv[0][0])) {
505                         case 'c': /* CIP/CTP */
506                                 switch (tolower(argv[0][1])) {
507                                 case 'i':
508                                         service = SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS;
509                                         break;
510
511                                 case 't':
512                                         service = SDP_SERVICE_CLASS_CORDLESS_TELEPHONY;
513                                         break;
514
515                                 default:
516                                         return (USAGE);
517                                         /* NOT REACHED */
518                                 }
519                                 break;
520
521                         case 'd': /* DialUp Networking */
522                                 service = SDP_SERVICE_CLASS_DIALUP_NETWORKING;
523                                 break;
524
525                         case 'f': /* Fax/OBEX File Transfer */
526                                 switch (tolower(argv[0][1])) {
527                                 case 'a':
528                                         service = SDP_SERVICE_CLASS_FAX;
529                                         break;
530
531                                 case 't':
532                                         service = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER;
533                                         break;
534
535                                 default:
536                                         return (USAGE);
537                                         /* NOT REACHED */
538                                 }
539                                 break;
540
541                         case 'g': /* GN */
542                                 service = SDP_SERVICE_CLASS_GN;
543                                 break;
544
545                         case 'h': /* Headset/HID */
546                                 switch (tolower(argv[0][1])) {
547                                 case 'i':
548                                         service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE;
549                                         break;
550
551                                 case 's':
552                                         service = SDP_SERVICE_CLASS_HEADSET;
553                                         break;
554
555                                 default:
556                                         return (USAGE);
557                                         /* NOT REACHED */
558                                 }
559                                 break;
560
561                         case 'l': /* LAN Access Using PPP */
562                                 service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP;
563                                 break;
564
565                         case 'n': /* NAP */
566                                 service = SDP_SERVICE_CLASS_NAP;
567                                 break;
568
569                         case 'o': /* OBEX Object Push */
570                                 service = SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH;
571                                 break;
572
573                         case 's': /* Serial Port */
574                                 service = SDP_SERVICE_CLASS_SERIAL_PORT;
575                                 break;
576
577                         default:
578                                 return (USAGE);
579                                 /* NOT REACHED */
580                         }
581                 } else
582                         service = (uint16_t) n;
583                 break;
584
585         default:
586                 return (USAGE);
587         }
588
589         /* Initialize attribute values array */
590         for (n = 0; n < values_len; n ++) {
591                 values[n].flags = SDP_ATTR_INVALID;
592                 values[n].attr = 0;
593                 values[n].vlen = BSIZE;
594                 values[n].value = buffer[n];
595         }
596
597         /* Do SDP Service Search Attribute Request */
598         n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values);
599         if (n != 0)
600                 return (ERROR);
601
602         /* Print attributes values */
603         for (n = 0; n < values_len; n ++) {
604                 if (values[n].flags != SDP_ATTR_OK)
605                         break;
606
607                 switch (values[n].attr) {
608                 case SDP_ATTR_SERVICE_RECORD_HANDLE:
609                         fprintf(stdout, "\n");
610                         if (values[n].vlen == 5) {
611                                 SDP_GET8(type, values[n].value);
612                                 if (type == SDP_DATA_UINT32) {
613                                         SDP_GET32(value, values[n].value);
614                                         fprintf(stdout, "Record Handle: " \
615                                                         "%#8.8x\n", value);
616                                 } else
617                                         fprintf(stderr, "Invalid type=%#x " \
618                                                         "Record Handle " \
619                                                         "attribute!\n", type);
620                         } else
621                                 fprintf(stderr, "Invalid size=%d for Record " \
622                                                 "Handle attribute\n",
623                                                 values[n].vlen);
624                         break;
625
626                 case SDP_ATTR_SERVICE_CLASS_ID_LIST:
627                         fprintf(stdout, "Service Class ID List:\n");
628                         print_service_class_id_list(values[n].value,
629                                         values[n].value + values[n].vlen);
630                         break;
631
632                 case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
633                         fprintf(stdout, "Protocol Descriptor List:\n");
634                         print_protocol_descriptor_list(values[n].value,
635                                         values[n].value + values[n].vlen);
636                         break;
637
638                 case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST:
639                         fprintf(stdout, "Bluetooth Profile Descriptor List:\n");
640                         print_bluetooth_profile_descriptor_list(values[n].value,
641                                         values[n].value + values[n].vlen);
642                         break;
643
644                 default:
645                         fprintf(stderr, "Unexpected attribute ID=%#4.4x\n",
646                                         values[n].attr);
647                         break;
648                 }
649         }
650
651         return (OK);
652 } /* do_sdp_search */
653
654 /* Perform SDP browse command */
655 static int
656 do_sdp_browse(void *xs, int argc, char **argv)
657 {
658 #undef  _STR
659 #undef  STR
660 #define _STR(x) #x
661 #define STR(x)  _STR(x)
662
663         static char const * const       av[] = {
664                 STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP),
665                 NULL
666         }; 
667
668         switch (argc) {
669         case 0:
670                 argc = 1;
671                 argv = (char **) av;
672                 /* FALL THROUGH */
673         case 1:
674                 return (do_sdp_search(xs, argc, argv));
675         }
676
677         return (USAGE);
678 } /* do_sdp_browse */
679
680 /* List of SDP commands */
681 struct sdp_command      sdp_commands[] = {
682 {
683 "Browse [<Group>]",
684 "Browse for services. The <Group> parameter is a 16-bit UUID of the group\n" \
685 "to browse. If omitted <Group> is set to Public Browse Group.\n\n" \
686 "\t<Group> - xxxx; 16-bit UUID of the group to browse\n",
687 do_sdp_browse
688 },
689 {
690 "Search <Service>",
691 "Search for the <Service>. The <Service> parameter is a 16-bit UUID of the\n" \
692 "service to search for. For some services it is possible to use service name\n"\
693 "instead of service UUID\n\n" \
694 "\t<Service> - xxxx; 16-bit UUID of the service to search for\n\n" \
695 "\tKnown service names\n" \
696 "\t===================\n" \
697 "\tCIP   - Common ISDN Access\n" \
698 "\tCTP   - Cordless Telephony\n" \
699 "\tDUN   - DialUp Networking\n" \
700 "\tFAX   - Fax\n" \
701 "\tFTRN  - OBEX File Transfer\n" \
702 "\tGN    - GN\n" \
703 "\tHID   - Human Interface Device\n" \
704 "\tHSET  - Headset\n" \
705 "\tLAN   - LAN Access Using PPP\n" \
706 "\tNAP   - Network Access Point\n" \
707 "\tOPUSH - OBEX Object Push\n" \
708 "\tSP    - Serial Port\n",
709 do_sdp_search
710 },
711 { NULL, NULL, NULL }
712 };
713