No empty .Rs/.Re
[netbsd-mini2440.git] / usr.bin / sdpquery / print.c
blobedb82ebbb840da664c6a50f21ab88687d2e43edf
1 /* $NetBSD: print.c,v 1.4 2009/08/20 11:07:42 plunky Exp $ */
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Iain Hibbert.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: print.c,v 1.4 2009/08/20 11:07:42 plunky Exp $");
35 #include <ctype.h>
36 #include <iconv.h>
37 #include <langinfo.h>
38 #include <sdp.h>
39 #include <stdbool.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <uuid.h>
44 #include <vis.h>
46 #include "sdpquery.h"
48 typedef struct {
49 uint16_t id;
50 const char * desc;
51 void (*print)(sdp_data_t *);
52 } attr_t;
54 typedef struct {
55 uint16_t class;
56 const char * desc;
57 attr_t * attrs;
58 size_t nattr;
59 } service_t;
61 typedef struct {
62 uint16_t base;
63 const char * codeset;
64 } language_t;
66 static const char *string_uuid(uuid_t *);
67 static const char *string_vis(int, const char *, size_t);
69 static void print_hexdump(const char *, const uint8_t *, size_t);
70 static bool print_attribute(uint16_t, sdp_data_t *, attr_t *, int);
71 static bool print_universal_attribute(uint16_t, sdp_data_t *);
72 static bool print_language_attribute(uint16_t, sdp_data_t *);
73 static bool print_service_attribute(uint16_t, sdp_data_t *);
75 static void print_bool(sdp_data_t *);
76 static void print_uint8d(sdp_data_t *);
77 static void print_uint8x(sdp_data_t *);
78 static void print_uint16d(sdp_data_t *);
79 static void print_uint16x(sdp_data_t *);
80 static void print_uint32x(sdp_data_t *);
81 static void print_uint32d(sdp_data_t *);
82 static void print_uuid(sdp_data_t *);
83 static void print_uuid_list(sdp_data_t *);
84 static void print_string(sdp_data_t *);
85 static void print_url(sdp_data_t *);
86 static void print_profile_version(sdp_data_t *);
87 static void print_language_string(sdp_data_t *);
89 static void print_service_class_id_list(sdp_data_t *);
90 static void print_protocol_descriptor(sdp_data_t *);
91 static void print_protocol_descriptor_list(sdp_data_t *);
92 static void print_language_base_attribute_id_list(sdp_data_t *);
93 static void print_service_availability(sdp_data_t *);
94 static void print_bluetooth_profile_descriptor_list(sdp_data_t *);
95 static void print_additional_protocol_descriptor_lists(sdp_data_t *);
96 static void print_sds_version_number_list(sdp_data_t *);
97 static void print_ct_network(sdp_data_t *);
98 static void print_asrc_features(sdp_data_t *);
99 static void print_asink_features(sdp_data_t *);
100 static void print_avrcp_features(sdp_data_t *);
101 static void print_supported_data_stores(sdp_data_t *);
102 static void print_supported_formats(sdp_data_t *);
103 static void print_hid_version(sdp_data_t *);
104 static void print_hid_device_subclass(sdp_data_t *);
105 static void print_hid_descriptor_list(sdp_data_t *);
106 static void print_security_description(sdp_data_t *);
107 static void print_hf_features(sdp_data_t *);
108 static void print_hfag_network(sdp_data_t *);
109 static void print_hfag_features(sdp_data_t *);
110 static void print_net_access_type(sdp_data_t *);
111 static void print_pnp_source(sdp_data_t *);
112 static void print_mas_types(sdp_data_t *);
113 static void print_supported_repositories(sdp_data_t *);
115 static void print_rfcomm(sdp_data_t *);
116 static void print_bnep(sdp_data_t *);
117 static void print_avctp(sdp_data_t *);
118 static void print_avdtp(sdp_data_t *);
119 static void print_l2cap(sdp_data_t *);
121 attr_t protocol_list[] = {
122 { 0x0001, "SDP", NULL },
123 { 0x0002, "UDP", NULL },
124 { 0x0003, "RFCOMM", print_rfcomm },
125 { 0x0004, "TCP", NULL },
126 { 0x0005, "TCS_BIN", NULL },
127 { 0x0006, "TCS_AT", NULL },
128 { 0x0008, "OBEX", NULL },
129 { 0x0009, "IP", NULL },
130 { 0x000a, "FTP", NULL },
131 { 0x000c, "HTTP", NULL },
132 { 0x000e, "WSP", NULL },
133 { 0x000f, "BNEP", print_bnep },
134 { 0x0010, "UPNP", NULL },
135 { 0x0011, "HIDP", NULL },
136 { 0x0012, "HARDCOPY_CONTROL_CHANNEL", NULL },
137 { 0x0014, "HARDCOPY_DATA_CHANNEL", NULL },
138 { 0x0016, "HARDCOPY_NOTIFICATION", NULL },
139 { 0x0017, "AVCTP", print_avctp },
140 { 0x0019, "AVDTP", print_avdtp },
141 { 0x001b, "CMTP", NULL },
142 { 0x001d, "UDI_C_PLANE", NULL },
143 { 0x001e, "MCAP_CONTROL_CHANNEL", NULL },
144 { 0x001f, "MCAP_DATA_CHANNEL", NULL },
145 { 0x0100, "L2CAP", print_l2cap },
148 attr_t universal_attrs[] = {
149 { 0x0000, "ServiceRecordHandle", print_uint32x },
150 { 0x0001, "ServiceClassIDList", print_service_class_id_list },
151 { 0x0002, "ServiceRecordState", print_uint32x },
152 { 0x0003, "ServiceID", print_uuid },
153 { 0x0004, "ProtocolDescriptorList", print_protocol_descriptor_list },
154 { 0x0005, "BrowseGroupList", print_uuid_list },
155 { 0x0006, "LanguageBaseAttributeIDList", print_language_base_attribute_id_list },
156 { 0x0007, "ServiceInfoTimeToLive", print_uint32d },
157 { 0x0008, "ServiceAvailability", print_service_availability },
158 { 0x0009, "BluetoothProfileDescriptorList", print_bluetooth_profile_descriptor_list },
159 { 0x000a, "DocumentationURL", print_url },
160 { 0x000b, "ClientExecutableURL", print_url },
161 { 0x000c, "IconURL", print_url },
162 { 0x000d, "AdditionalProtocolDescriptorLists", print_additional_protocol_descriptor_lists },
165 attr_t language_attrs[] = { /* Language Attribute Offsets */
166 { 0x0000, "ServiceName", print_language_string },
167 { 0x0001, "ServiceDescription", print_language_string },
168 { 0x0002, "ProviderName", print_language_string },
171 attr_t sds_attrs[] = { /* Service Discovery Server */
172 { 0x0200, "VersionNumberList", print_sds_version_number_list },
173 { 0x0201, "ServiceDatabaseState", print_uint32x },
176 attr_t bgd_attrs[] = { /* Browse Group Descriptor */
177 { 0x0200, "GroupID", print_uuid },
180 attr_t ct_attrs[] = { /* Cordless Telephony */
181 { 0x0301, "ExternalNetwork", print_ct_network },
184 attr_t asrc_attrs[] = { /* Audio Source */
185 { 0x0311, "SupportedFeatures", print_asrc_features },
188 attr_t asink_attrs[] = { /* Audio Sink */
189 { 0x0311, "SupportedFeatures", print_asink_features },
192 attr_t avrcp_attrs[] = { /* Audio Video Remote Control Profile */
193 { 0x0311, "SupportedFeatures", print_avrcp_features },
196 attr_t lan_attrs[] = { /* LAN Access Using PPP */
197 { 0x0200, "IPSubnet", print_string },
200 attr_t dun_attrs[] = { /* Dialup Networking */
201 { 0x0305, "AudioFeedbackSupport", print_bool },
204 attr_t irmc_sync_attrs[] = { /* IrMC Sync */
205 { 0x0301, "SupportedDataStoresList", print_supported_data_stores },
208 attr_t opush_attrs[] = { /* Object Push */
209 { 0x0303, "SupportedFormatsList", print_supported_formats },
212 attr_t hset_attrs[] = { /* Headset */
213 { 0x0302, "RemoteAudioVolumeControl", print_bool },
216 attr_t fax_attrs[] = { /* Fax */
217 { 0x0302, "FAXClass1", print_bool },
218 { 0x0303, "FAXClass2.0", print_bool },
219 { 0x0304, "FAXClass2", print_bool },
220 { 0x0305, "AudioFeedbackSupport", print_bool },
223 attr_t panu_attrs[] = { /* Personal Area Networking User */
224 { 0x030a, "SecurityDescription", print_security_description },
227 attr_t nap_attrs[] = { /* Network Access Point */
228 { 0x030a, "SecurityDescription", print_security_description },
229 { 0x030b, "NetAccessType", print_net_access_type },
230 { 0x030c, "MaxNetAccessRate", print_uint32d },
231 { 0x030d, "IPv4Subnet", print_string },
232 { 0x030e, "IPv6Subnet", print_string },
235 attr_t gn_attrs[] = { /* Group Network */
236 { 0x030a, "SecurityDescription", print_security_description },
237 { 0x030d, "IPv4Subnet", print_string },
238 { 0x030e, "IPv6Subnet", print_string },
241 attr_t hf_attrs[] = { /* Handsfree */
242 { 0x0311, "SupportedFeatures", print_hf_features },
245 attr_t hfag_attrs[] = { /* Handsfree Audio Gateway */
246 { 0x0301, "Network", print_hfag_network },
247 { 0x0311, "SupportedFeatures", print_hfag_features },
250 attr_t hid_attrs[] = { /* Human Interface Device */
251 { 0x0200, "HIDDeviceReleaseNumber", print_hid_version },
252 { 0x0201, "HIDParserVersion", print_hid_version },
253 { 0x0202, "HIDDeviceSubClass", print_hid_device_subclass },
254 { 0x0203, "HIDCountryCode", print_uint8x },
255 { 0x0204, "HIDVirtualCable", print_bool },
256 { 0x0205, "HIDReconnectInitiate", print_bool },
257 { 0x0206, "HIDDescriptorList", print_hid_descriptor_list },
258 { 0x0207, "HIDLANGIDBaseList", NULL },
259 { 0x0208, "HIDSDPDisable", print_bool },
260 { 0x0209, "HIDBatteryPower", print_bool },
261 { 0x020a, "HIDRemoteWake", print_bool },
262 { 0x020b, "HIDProfileVersion", print_profile_version },
263 { 0x020c, "HIDSupervisionTimeout", print_uint16d },
264 { 0x020d, "HIDNormallyConnectable", print_bool },
265 { 0x020e, "HIDBootDevice", print_bool },
268 attr_t pnp_attrs[] = { /* Device ID */
269 { 0x0200, "SpecificationID", print_profile_version },
270 { 0x0201, "VendorID", print_uint16x },
271 { 0x0202, "ProductID", print_uint16x },
272 { 0x0203, "Version", print_hid_version },
273 { 0x0204, "PrimaryRecord", print_bool },
274 { 0x0205, "VendorIDSource", print_pnp_source },
277 attr_t mas_attrs[] = { /* Message Access Server */
278 { 0x0315, "InstanceID", print_uint8d },
279 { 0x0316, "SupportedMessageTypes", print_mas_types },
282 attr_t pse_attrs[] = { /* Phonebook Access Server */
283 { 0x0314, "SupportedRepositories", print_supported_repositories },
286 #define A(a) a, __arraycount(a)
287 service_t service_list[] = {
288 { 0x1000, "Service Discovery Server", A(sds_attrs) },
289 { 0x1001, "Browse Group Descriptor", A(bgd_attrs) },
290 { 0x1002, "Public Browse Root", NULL, 0 },
291 { 0x1101, "Serial Port", NULL, 0 },
292 { 0x1102, "LAN Access Using PPP", A(lan_attrs) },
293 { 0x1103, "Dialup Networking", A(dun_attrs) },
294 { 0x1104, "IrMC Sync", A(irmc_sync_attrs) },
295 { 0x1105, "Object Push", A(opush_attrs) },
296 { 0x1106, "File Transfer", NULL, 0 },
297 { 0x1107, "IrMC Sync Command", NULL, 0 },
298 { 0x1108, "Headset", A(hset_attrs) },
299 { 0x1109, "Cordless Telephony", A(ct_attrs) },
300 { 0x110a, "Audio Source", A(asrc_attrs) },
301 { 0x110b, "Audio Sink", A(asink_attrs) },
302 { 0x110c, "A/V Remote Control Target", A(avrcp_attrs) },
303 { 0x110d, "Advanced Audio Distribution", NULL, 0 },
304 { 0x110e, "A/V Remote Control", A(avrcp_attrs) },
305 { 0x110f, "Video Conferencing", NULL, 0 },
306 { 0x1110, "Intercom", NULL, 0 },
307 { 0x1111, "Fax", A(fax_attrs) },
308 { 0x1112, "Headset Audio Gateway", NULL, 0 },
309 { 0x1113, "WAP", NULL, 0 },
310 { 0x1114, "WAP Client", NULL, 0 },
311 { 0x1115, "Personal Area Networking User", A(panu_attrs) },
312 { 0x1116, "Network Access Point", A(nap_attrs) },
313 { 0x1117, "Group Network", A(gn_attrs) },
314 { 0x1118, "Direct Printing", NULL, 0 },
315 { 0x1119, "Reference Printing", NULL, 0 },
316 { 0x111a, "Imaging", NULL, 0 },
317 { 0x111b, "Imaging Responder", NULL, 0 },
318 { 0x111c, "Imaging Automatic Archive", NULL, 0 },
319 { 0x111d, "Imaging Referenced Objects", NULL, 0 },
320 { 0x111e, "Handsfree", A(hf_attrs) },
321 { 0x111f, "Handsfree Audio Gateway", A(hfag_attrs) },
322 { 0x1120, "Direct Printing Reference Objects", NULL, 0 },
323 { 0x1121, "Reflected User Interface", NULL, 0 },
324 { 0x1122, "Basic Printing", NULL, 0 },
325 { 0x1123, "Printing Status", NULL, 0 },
326 { 0x1124, "Human Interface Device", A(hid_attrs) },
327 { 0x1125, "Hardcopy Cable Replacement", NULL, 0 },
328 { 0x1126, "Hardcopy Cable Replacement Print", NULL, 0 },
329 { 0x1127, "Hardcopy Cable Replacement Scan", NULL, 0 },
330 { 0x1128, "Common ISDN Access", NULL, 0 },
331 { 0x1129, "Video Conferencing GW", NULL, 0 },
332 { 0x112a, "UDI MT", NULL, 0 },
333 { 0x112b, "UDI TA", NULL, 0 },
334 { 0x112c, "Audio/Video", NULL, 0 },
335 { 0x112d, "SIM Access", NULL, 0 },
336 { 0x112e, "Phonebook Access Client", NULL, 0 },
337 { 0x112f, "Phonebook Access Server", A(pse_attrs) },
338 { 0x1130, "Phonebook Access", NULL, 0 },
339 { 0x1131, "Headset HS", NULL, 0 },
340 { 0x1132, "Message Access Server", A(mas_attrs) },
341 { 0x1133, "Message Notification Server", NULL, 0 },
342 { 0x1134, "Message Access Profile", NULL, 0 },
343 { 0x1200, "PNP Information", A(pnp_attrs) },
344 { 0x1201, "Generic Networking", NULL, 0 },
345 { 0x1202, "Generic File Transfer", NULL, 0 },
346 { 0x1203, "Generic Audio", NULL, 0 },
347 { 0x1204, "Generic Telephony", NULL, 0 },
348 { 0x1205, "UPNP", NULL, 0 },
349 { 0x1206, "UPNP IP", NULL, 0 },
350 { 0x1300, "UPNP IP PAN", NULL, 0 },
351 { 0x1301, "UPNP IP LAP", NULL, 0 },
352 { 0x1302, "UPNP IP L2CAP", NULL, 0 },
353 { 0x1303, "Video Source", NULL, 0 },
354 { 0x1304, "Video Sink", NULL, 0 },
355 { 0x1305, "Video Distribution", NULL, 0 },
356 { 0x1400, "HDP", NULL, 0 },
357 { 0x1401, "HDP Source", NULL, 0 },
358 { 0x1402, "HDP Sink", NULL, 0 },
360 #undef A
362 /* extracted Service Class ID List */
363 #define MAX_SERVICES 16
364 static size_t nservices;
365 static uint16_t service_class[MAX_SERVICES];
367 /* extracted Language Base Attribute ID List */
368 #define MAX_LANGUAGES 16
369 static int nlanguages;
370 static language_t language[MAX_LANGUAGES];
371 static int current;
373 static bool
374 sdp_get_uint8(sdp_data_t *d, uint8_t *vp)
376 uintmax_t v;
378 if (sdp_data_type(d) != SDP_DATA_UINT8
379 || !sdp_get_uint(d, &v))
380 return false;
382 *vp = (uint8_t)v;
383 return true;
386 static bool
387 sdp_get_uint16(sdp_data_t *d, uint16_t *vp)
389 uintmax_t v;
391 if (sdp_data_type(d) != SDP_DATA_UINT16
392 || !sdp_get_uint(d, &v))
393 return false;
395 *vp = (uint16_t)v;
396 return true;
399 static bool
400 sdp_get_uint32(sdp_data_t *d, uint32_t *vp)
402 uintmax_t v;
404 if (sdp_data_type(d) != SDP_DATA_UINT32
405 || !sdp_get_uint(d, &v))
406 return false;
408 *vp = (uint32_t)v;
409 return true;
412 void
413 print_record(sdp_data_t *rec)
415 sdp_data_t value;
416 uint16_t id;
418 nservices = 0;
419 nlanguages = 0;
420 current = -1;
422 while (sdp_get_attr(rec, &id, &value)) {
423 if (Xflag) {
424 printf("AttributeID 0x%04x:\n", id);
425 print_hexdump(" ", value.next, value.end - value.next);
426 } else if (Rflag) {
427 printf("AttributeID 0x%04x:\n", id);
428 sdp_data_print(&value, 4);
429 } else if (print_universal_attribute(id, &value)
430 || print_language_attribute(id, &value)
431 || print_service_attribute(id, &value)) {
432 if (value.next != value.end)
433 printf(" [additional data ignored]\n");
434 } else {
435 printf("AttributeID 0x%04x:\n", id);
436 sdp_data_print(&value, 4);
441 static const char *
442 string_uuid(uuid_t *uuid)
444 static char buf[64];
445 const char *desc;
446 uuid_t u;
447 size_t i;
449 u = *uuid;
450 u.time_low = 0;
451 if (!uuid_equal(&u, &BLUETOOTH_BASE_UUID, NULL)) {
452 snprintf(buf, sizeof(buf),
453 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
454 uuid->time_low, uuid->time_mid, uuid->time_hi_and_version,
455 uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low,
456 uuid->node[0], uuid->node[1], uuid->node[2],
457 uuid->node[3], uuid->node[4], uuid->node[5]);
459 return buf;
462 desc = NULL;
463 for (i = 0; i < __arraycount(service_list); i++) {
464 if (uuid->time_low == service_list[i].class) {
465 desc = service_list[i].desc;
466 break;
470 for (i = 0; i < __arraycount(protocol_list); i++) {
471 if (uuid->time_low == protocol_list[i].id) {
472 desc = protocol_list[i].desc;
473 break;
477 if (!Nflag && desc) {
478 snprintf(buf, sizeof(buf), "%s", desc);
479 return buf;
482 snprintf(buf, sizeof(buf), "%s%s(0x%*.*x)",
483 (desc == NULL ? "" : desc),
484 (desc == NULL ? "" : " "),
485 (uuid->time_low > UINT16_MAX ? 8 : 4),
486 (uuid->time_low > UINT16_MAX ? 8 : 4),
487 uuid->time_low);
489 return buf;
492 static const char *
493 string_vis(int style, const char *src, size_t len)
495 static char buf[50];
496 char *dst = buf;
498 style |= VIS_NL;
499 while (len > 0 && (dst + 5) < (buf + sizeof(buf))) {
500 dst = vis(dst, src[0], style, (len > 1 ? src[1] : 0));
501 src++;
502 len--;
505 return buf;
508 static void
509 print_hexdump(const char *title, const uint8_t *data, size_t len)
511 int n, i;
513 i = 0;
514 n = printf("%s", title);
516 while (len-- > 0) {
517 if (++i > 8) {
518 printf("\n%*s", n, "");
519 i = 1;
522 printf(" 0x%02x", *data++);
525 printf("\n");
528 static bool
529 print_attribute(uint16_t id, sdp_data_t *value, attr_t *attr, int count)
531 int i;
533 for (i = 0; i < count; i++) {
534 if (id == attr[i].id) {
535 printf("%s", attr[i].desc);
537 if (Nflag) {
538 printf(" (");
540 if (current != -1)
541 printf("0x%04x + ", language[current].base);
543 printf("0x%04x)", id);
546 printf(": ");
548 if (attr[i].print == NULL) {
549 printf("\n");
550 sdp_data_print(value, 4);
551 value->next = value->end;
552 } else {
553 (attr[i].print)(value);
556 return true;
560 return false;
563 static bool
564 print_universal_attribute(uint16_t id, sdp_data_t *value)
567 return print_attribute(id, value,
568 universal_attrs, __arraycount(universal_attrs));
571 static bool
572 print_language_attribute(uint16_t id, sdp_data_t *value)
574 bool done = false;
576 for (current = 0; current < nlanguages && !done; current++)
577 done = print_attribute(id - language[current].base, value,
578 language_attrs, __arraycount(language_attrs));
580 current = -1;
581 return done;
584 static bool
585 print_service_attribute(uint16_t id, sdp_data_t *value)
587 size_t i, j;
589 for (i = 0; i < nservices; i++) {
590 for (j = 0; j < __arraycount(service_list); j++) {
591 if (service_class[i] == service_list[j].class)
592 return print_attribute(id, value,
593 service_list[j].attrs,
594 service_list[j].nattr);
598 return false;
601 static void
602 print_bool(sdp_data_t *data)
604 bool v;
606 if (!sdp_get_bool(data, &v))
607 return;
609 printf("%s\n", (v ? "true" : "false"));
612 static void
613 print_uint8d(sdp_data_t *data)
615 uint8_t v;
617 if (!sdp_get_uint8(data, &v))
618 return;
620 printf("%d\n", v);
623 static void
624 print_uint8x(sdp_data_t *data)
626 uint8_t v;
628 if (!sdp_get_uint8(data, &v))
629 return;
631 printf("0x%02x\n", v);
634 static void
635 print_uint16d(sdp_data_t *data)
637 uint16_t v;
639 if (!sdp_get_uint16(data, &v))
640 return;
642 printf("%d\n", v);
645 static void
646 print_uint16x(sdp_data_t *data)
648 uint16_t v;
650 if (!sdp_get_uint16(data, &v))
651 return;
653 printf("0x%04x\n", v);
656 static void
657 print_uint32x(sdp_data_t *data)
659 uint32_t v;
661 if (!sdp_get_uint32(data, &v))
662 return;
664 printf("0x%08x\n", v);
667 static void
668 print_uint32d(sdp_data_t *data)
670 uint32_t v;
672 if (!sdp_get_uint32(data, &v))
673 return;
675 printf("%d\n", v);
678 static void
679 print_uuid(sdp_data_t *data)
681 uuid_t uuid;
683 if (!sdp_get_uuid(data, &uuid))
684 return;
686 printf("%s\n", string_uuid(&uuid));
689 static void
690 print_uuid_list(sdp_data_t *data)
692 sdp_data_t seq;
693 uuid_t uuid;
695 if (!sdp_get_seq(data, &seq))
696 return;
698 printf("\n");
699 while (sdp_get_uuid(&seq, &uuid))
700 printf(" %s\n", string_uuid(&uuid));
702 if (seq.next != seq.end)
703 printf(" [additional data]\n");
706 static void
707 print_string(sdp_data_t *data)
709 char *str;
710 size_t len;
712 if (!sdp_get_str(data, &str, &len))
713 return;
715 printf("\"%s\"\n", string_vis(VIS_CSTYLE, str, len));
718 static void
719 print_url(sdp_data_t *data)
721 char *url;
722 size_t len;
724 if (!sdp_get_url(data, &url, &len))
725 return;
727 printf("\"%s\"\n", string_vis(VIS_HTTPSTYLE, url, len));
730 static void
731 print_profile_version(sdp_data_t *data)
733 uint16_t v;
735 if (!sdp_get_uint16(data, &v))
736 return;
738 printf("v%d.%d\n", (v >> 8), (v & 0xff));
742 * This should only be called through print_language_attribute() which
743 * sets codeset of the string to be printed.
745 static void
746 print_language_string(sdp_data_t *data)
748 char buf[50], *dst, *src;
749 iconv_t ih;
750 size_t n, srcleft, dstleft;
752 if (!sdp_get_str(data, &src, &srcleft))
753 return;
755 dst = buf;
756 dstleft = sizeof(buf);
758 ih = iconv_open(nl_langinfo(CODESET), language[current].codeset);
759 if (ih == (iconv_t)-1) {
760 printf("Can't convert %s string\n", language[current].codeset);
761 return;
764 n = iconv(ih, (const char **)&src, &srcleft, &dst, &dstleft);
766 iconv_close(ih);
768 if (Nflag || n > 0)
769 printf("(%s) ", language[current].codeset);
771 printf("\"%.*s%s\n", (int)(sizeof(buf) - dstleft), buf,
772 (srcleft > 0 ? " ..." : "\""));
775 static void
776 print_service_class_id_list(sdp_data_t *data)
778 sdp_data_t seq;
779 uuid_t uuid;
781 if (!sdp_get_seq(data, &seq))
782 return;
784 printf("\n");
785 while (sdp_get_uuid(&seq, &uuid)) {
786 printf(" %s\n", string_uuid(&uuid));
788 if (nservices < MAX_SERVICES) {
789 service_class[nservices] = uuid.time_low;
790 uuid.time_low = 0;
791 if (uuid_equal(&uuid, &BLUETOOTH_BASE_UUID, NULL))
792 nservices++;
796 if (seq.next != seq.end)
797 printf(" [additional data]\n");
800 static void
801 print_protocol_descriptor(sdp_data_t *data)
803 uuid_t u0, uuid;
804 size_t i;
806 if (!sdp_get_uuid(data, &uuid))
807 return;
809 u0 = uuid;
810 u0.time_low = 0;
811 if (uuid_equal(&u0, &BLUETOOTH_BASE_UUID, NULL)) {
812 for (i = 0; i < __arraycount(protocol_list); i++) {
813 if (uuid.time_low == protocol_list[i].id) {
814 printf(" %s", protocol_list[i].desc);
816 if (Nflag)
817 printf(" (0x%04x)", protocol_list[i].id);
819 if (protocol_list[i].print)
820 (protocol_list[i].print)(data);
822 if (data->next != data->end)
823 printf(" [additional data ignored]");
825 printf("\n");
826 return;
831 printf(" %s\n", string_uuid(&uuid));
832 sdp_data_print(data, 4);
833 data->next = data->end;
836 static void
837 print_protocol_descriptor_list(sdp_data_t *data)
839 sdp_data_t seq, proto;
841 printf("\n");
842 sdp_get_alt(data, data); /* strip [optional] alt header */
844 while (sdp_get_seq(data, &seq))
845 while (sdp_get_seq(&seq, &proto))
846 print_protocol_descriptor(&proto);
849 static void
850 print_language_base_attribute_id_list(sdp_data_t *data)
852 sdp_data_t list;
853 uint16_t v;
854 const char *codeset;
855 char lang[2];
857 if (!sdp_get_seq(data, &list))
858 return;
860 printf("\n");
861 while (list.next < list.end) {
863 * ISO-639-1 natural language values are published at
864 * http://www.loc.gov/standards/iso639-2/php/code-list.php
866 if (!sdp_get_uint16(&list, &v))
867 break;
869 be16enc(lang, v);
870 if (!islower((int)lang[0]) || !islower((int)lang[1]))
871 break;
874 * MIBenum values are published at
875 * http://www.iana.org/assignments/character-sets
877 if (!sdp_get_uint16(&list, &v))
878 break;
880 switch(v) {
881 case 3: codeset = "US-ASCII"; break;
882 case 4: codeset = "ISO-8859-1"; break;
883 case 5: codeset = "ISO-8859-2"; break;
884 case 106: codeset = "UTF-8"; break;
885 case 1013: codeset = "UTF-16BE"; break;
886 case 1014: codeset = "UTF-16LE"; break;
887 default: codeset = "Unknown"; break;
890 if (!sdp_get_uint16(&list, &v))
891 break;
893 printf(" %.2s.%s base 0x%04x\n", lang, codeset, v);
895 if (nlanguages < MAX_LANGUAGES) {
896 language[nlanguages].base = v;
897 language[nlanguages].codeset = codeset;
898 nlanguages++;
902 if (list.next != list.end)
903 printf(" [additional data]\n");
906 static void
907 print_service_availability(sdp_data_t *data)
909 uint8_t v;
911 if (!sdp_get_uint8(data, &v))
912 return;
914 printf("%d/%d\n", v, UINT8_MAX);
917 static void
918 print_bluetooth_profile_descriptor_list(sdp_data_t *data)
920 sdp_data_t seq, profile;
921 uuid_t uuid;
922 uint16_t v;
924 if (!sdp_get_seq(data, &seq))
925 return;
927 printf("\n");
928 while (seq.next < seq.end) {
929 if (!sdp_get_seq(&seq, &profile)
930 || !sdp_get_uuid(&profile, &uuid)
931 || !sdp_get_uint16(&profile, &v))
932 break;
934 printf(" %s, v%d.%d", string_uuid(&uuid),
935 (v >> 8), (v & 0xff));
937 if (profile.next != profile.end)
938 printf(" [additional profile data]");
940 printf("\n");
943 if (seq.next != seq.end)
944 printf(" [additional data]\n");
947 static void
948 print_additional_protocol_descriptor_lists(sdp_data_t *data)
950 sdp_data_t seq, stack, proto;
952 printf("\n");
953 sdp_get_seq(data, &seq);
955 while (sdp_get_seq(&seq, &stack))
956 while (sdp_get_seq(&stack, &proto))
957 print_protocol_descriptor(&proto);
959 if (seq.next != seq.end)
960 printf(" [additional data]\n");
963 static void
964 print_sds_version_number_list(sdp_data_t *data)
966 sdp_data_t list;
967 const char *sep;
968 uint16_t v;
970 if (!sdp_get_seq(data, &list))
971 return;
973 sep = "";
974 while (sdp_get_uint16(&list, &v)) {
975 printf("%sv%d.%d", sep, (v >> 8), (v & 0xff));
976 sep = ", ";
979 if (list.next != list.end)
980 printf(" [additional data]");
982 printf("\n");
985 static void
986 print_ct_network(sdp_data_t *data)
988 uint8_t v;
990 if (!sdp_get_uint8(data, &v))
991 return;
993 switch (v) {
994 case 0x01: printf("PSTN"); break;
995 case 0x02: printf("ISDN"); break;
996 case 0x03: printf("GSM"); break;
997 case 0x04: printf("CDMA"); break;
998 case 0x05: printf("Analogue Cellular"); break;
999 case 0x06: printf("Packet Switched"); break;
1000 case 0x07: printf("Other"); break;
1001 default: printf("0x%02x", v); break;
1004 printf("\n");
1007 static void
1008 print_asrc_features(sdp_data_t *data)
1010 uint16_t v;
1012 if (!sdp_get_uint16(data, &v))
1013 return;
1015 if (Nflag)
1016 printf("(0x%04x)", v);
1018 printf("\n");
1019 if (v & (1<<0)) printf(" Player\n");
1020 if (v & (1<<1)) printf(" Microphone\n");
1021 if (v & (1<<2)) printf(" Tuner\n");
1022 if (v & (1<<3)) printf(" Mixer\n");
1025 static void
1026 print_asink_features(sdp_data_t *data)
1028 uint16_t v;
1030 if (!sdp_get_uint16(data, &v))
1031 return;
1033 if (Nflag)
1034 printf("(0x%04x)", v);
1036 printf("\n");
1037 if (v & (1<<0)) printf(" Headphone\n");
1038 if (v & (1<<1)) printf(" Speaker\n");
1039 if (v & (1<<2)) printf(" Recorder\n");
1040 if (v & (1<<3)) printf(" Amplifier\n");
1043 static void
1044 print_avrcp_features(sdp_data_t *data)
1046 uint16_t v;
1048 if (!sdp_get_uint16(data, &v))
1049 return;
1051 if (Nflag)
1052 printf("(0x%04x)", v);
1054 printf("\n");
1055 if (v & (1<<0)) printf(" Category 1\n");
1056 if (v & (1<<1)) printf(" Category 2\n");
1057 if (v & (1<<2)) printf(" Category 3\n");
1058 if (v & (1<<3)) printf(" Category 4\n");
1061 static void
1062 print_supported_data_stores(sdp_data_t *data)
1064 sdp_data_t list;
1065 const char *sep;
1066 uint8_t v;
1068 if (!sdp_get_seq(data, &list))
1069 return;
1071 sep = "\n ";
1072 while (sdp_get_uint8(&list, &v)) {
1073 printf(sep);
1074 sep = ", ";
1076 switch(v) {
1077 case 0x01: printf("Phonebook"); break;
1078 case 0x03: printf("Calendar"); break;
1079 case 0x05: printf("Notes"); break;
1080 case 0x06: printf("Messages"); break;
1081 default: printf("0x%02x", v); break;
1085 if (list.next != list.end)
1086 printf(" [additional data]");
1088 printf("\n");
1091 static void
1092 print_supported_formats(sdp_data_t *data)
1094 sdp_data_t list;
1095 const char *sep;
1096 uint8_t v;
1098 if (!sdp_get_seq(data, &list))
1099 return;
1101 sep = "\n ";
1102 while (sdp_get_uint8(&list, &v)) {
1103 printf(sep);
1104 sep = ", ";
1106 switch(v) {
1107 case 0x01: printf("vCard 2.1"); break;
1108 case 0x02: printf("vCard 3.0"); break;
1109 case 0x03: printf("vCal 1.0"); break;
1110 case 0x04: printf("iCal 2.0"); break;
1111 case 0x05: printf("vNote"); break;
1112 case 0x06: printf("vMessage"); break;
1113 case 0xff: printf("Any"); break;
1114 default: printf("0x%02x", v); break;
1118 if (list.next != list.end)
1119 printf(" [additional data]");
1121 printf("\n");
1124 static void
1125 print_hid_version(sdp_data_t *data)
1127 uint16_t v;
1129 if (!sdp_get_uint16(data, &v))
1130 return;
1132 printf("v%d.%d.%d\n",
1133 ((v & 0xff00) >> 8), ((v & 0x00f0) >> 4), (v & 0x000f));
1136 static void
1137 print_hid_device_subclass(sdp_data_t *data)
1139 uint8_t v;
1141 if (!sdp_get_uint8(data, &v))
1142 return;
1144 switch ((v & 0x3c) >> 2) {
1145 case 1: printf("Joystick"); break;
1146 case 2: printf("Gamepad"); break;
1147 case 3: printf("Remote Control"); break;
1148 case 4: printf("Sensing Device"); break;
1149 case 5: printf("Digitiser Tablet"); break;
1150 case 6: printf("Card Reader"); break;
1151 default: printf("Peripheral"); break;
1154 if (v & 0x40) printf(" <Keyboard>");
1155 if (v & 0x80) printf(" <Mouse>");
1157 printf("\n");
1160 static void
1161 print_hid_descriptor_list(sdp_data_t *data)
1163 sdp_data_t list, seq;
1164 uint8_t type;
1165 const char *name;
1166 char *str;
1167 size_t len;
1170 if (!sdp_get_seq(data, &list))
1171 return;
1173 printf("\n");
1174 while (list.next < list.end) {
1175 if (!sdp_get_seq(&list, &seq)
1176 || !sdp_get_uint8(&seq, &type)
1177 || !sdp_get_str(&seq, &str, &len))
1178 return;
1180 switch (type) {
1181 case 0x22: name = "Report"; break;
1182 case 0x23: name = "Physical Descriptor"; break;
1183 default: name = ""; break;
1186 printf(" Type 0x%02x: %s\n", type, name);
1187 print_hexdump(" Data", (uint8_t *)str, len);
1189 if (seq.next != seq.end)
1190 printf(" [additional data]\n");
1194 static void
1195 print_security_description(sdp_data_t *data)
1197 uint16_t v;
1199 if (!sdp_get_uint16(data, &v))
1200 return;
1202 switch (v) {
1203 case 0x0000: printf("None"); break;
1204 case 0x0001: printf("Service-level Security"); break;
1205 case 0x0002: printf("802.1x Security"); break;
1206 default: printf("0x%04x", v); break;
1209 printf("\n");
1212 static void
1213 print_hf_features(sdp_data_t *data)
1215 uint16_t v;
1217 if (!sdp_get_uint16(data, &v))
1218 return;
1220 if (Nflag)
1221 printf("(0x%04x)", v);
1223 printf("\n");
1224 if (v & (1<<0)) printf(" Echo Cancellation/Noise Reduction\n");
1225 if (v & (1<<1)) printf(" Call Waiting\n");
1226 if (v & (1<<2)) printf(" Caller Line Identification\n");
1227 if (v & (1<<3)) printf(" Voice Recognition\n");
1228 if (v & (1<<4)) printf(" Volume Control\n");
1231 static void
1232 print_hfag_network(sdp_data_t *data)
1234 uint8_t v;
1236 if (!sdp_get_uint8(data, &v))
1237 return;
1239 switch (v) {
1240 case 0x01: printf("Ability to reject a call"); break;
1241 case 0x02: printf("No ability to reject a call"); break;
1242 default: printf("0x%02x", v); break;
1245 printf("\n");
1248 static void
1249 print_hfag_features(sdp_data_t *data)
1251 uint16_t v;
1253 if (!sdp_get_uint16(data, &v))
1254 return;
1256 if (Nflag)
1257 printf("(0x%04x)", v);
1259 printf("\n");
1260 if (v & (1<<0)) printf(" 3 Way Calling\n");
1261 if (v & (1<<1)) printf(" Echo Cancellation/Noise Reduction\n");
1262 if (v & (1<<2)) printf(" Voice Recognition\n");
1263 if (v & (1<<3)) printf(" In-band Ring Tone\n");
1264 if (v & (1<<4)) printf(" Voice Tags\n");
1267 static void
1268 print_net_access_type(sdp_data_t *data)
1270 uint16_t v;
1272 if (!sdp_get_uint16(data, &v))
1273 return;
1275 switch(v) {
1276 case 0x0000: printf("PSTN"); break;
1277 case 0x0001: printf("ISDN"); break;
1278 case 0x0002: printf("DSL"); break;
1279 case 0x0003: printf("Cable Modem"); break;
1280 case 0x0004: printf("10Mb Ethernet"); break;
1281 case 0x0005: printf("100Mb Ethernet"); break;
1282 case 0x0006: printf("4Mb Token Ring"); break;
1283 case 0x0007: printf("16Mb Token Ring"); break;
1284 case 0x0008: printf("100Mb Token Ring"); break;
1285 case 0x0009: printf("FDDI"); break;
1286 case 0x000a: printf("GSM"); break;
1287 case 0x000b: printf("CDMA"); break;
1288 case 0x000c: printf("GPRS"); break;
1289 case 0x000d: printf("3G Cellular"); break;
1290 case 0xfffe: printf("other"); break;
1291 default: printf("0x%04x", v); break;
1294 printf("\n");
1297 static void
1298 print_pnp_source(sdp_data_t *data)
1300 uint16_t v;
1302 if (!sdp_get_uint16(data, &v))
1303 return;
1305 switch (v) {
1306 case 0x0001: printf("Bluetooth SIG"); break;
1307 case 0x0002: printf("USB Implementers Forum"); break;
1308 default: printf("0x%04x", v); break;
1311 printf("\n");
1314 static void
1315 print_mas_types(sdp_data_t *data)
1317 uint8_t v;
1319 if (!sdp_get_uint8(data, &v))
1320 return;
1322 if (Nflag)
1323 printf("(0x%02x)", v);
1325 printf("\n");
1326 if (v & (1<<0)) printf(" EMAIL\n");
1327 if (v & (1<<1)) printf(" SMS_GSM\n");
1328 if (v & (1<<2)) printf(" SMS_CDMA\n");
1329 if (v & (1<<3)) printf(" MMS\n");
1332 static void
1333 print_supported_repositories(sdp_data_t *data)
1335 uint8_t v;
1337 if (!sdp_get_uint8(data, &v))
1338 return;
1340 if (Nflag)
1341 printf("(0x%02x)", v);
1343 printf("\n");
1344 if (v & (1<<0)) printf(" Local Phonebook\n");
1345 if (v & (1<<1)) printf(" SIM Card\n");
1348 static void
1349 print_rfcomm(sdp_data_t *data)
1351 uint8_t v;
1353 if (sdp_get_uint8(data, &v))
1354 printf(" (channel %d)", v);
1357 static void
1358 print_bnep(sdp_data_t *data)
1360 sdp_data_t seq;
1361 uint16_t v;
1362 const char *sep;
1364 if (!sdp_get_uint16(data, &v)
1365 || !sdp_get_seq(data, &seq))
1366 return;
1368 printf(" (v%d.%d", (v >> 8), (v & 0xff));
1369 sep = "; ";
1370 while (sdp_get_uint16(&seq, &v)) {
1371 printf(sep);
1372 sep = ", ";
1374 switch (v) {
1375 case 0x0800: printf("IPv4"); break;
1376 case 0x0806: printf("ARP"); break;
1377 case 0x8100: printf("802.1Q"); break;
1378 case 0x86dd: printf("IPv6"); break;
1379 default: printf("0x%04x", v); break;
1382 printf(")");
1384 if (seq.next != seq.end)
1385 printf(" [additional data]");
1388 static void
1389 print_avctp(sdp_data_t *data)
1391 uint16_t v;
1393 if (sdp_get_uint16(data, &v))
1394 printf(" (v%d.%d)", (v >> 8), (v & 0xff));
1397 static void
1398 print_avdtp(sdp_data_t *data)
1400 uint16_t v;
1402 if (sdp_get_uint16(data, &v))
1403 printf(" (v%d.%d)", (v >> 8), (v & 0xff));
1406 static void
1407 print_l2cap(sdp_data_t *data)
1409 uint16_t v;
1411 if (sdp_get_uint16(data, &v))
1412 printf(" (PSM 0x%04x)", v);