1 /* $NetBSD: print.c,v 1.7 2010/12/14 15:18:20 plunky Exp $ */ 2 3 /*- 4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Iain Hibbert. 9 * 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. 18 * 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. 30 */ 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: print.c,v 1.7 2010/12/14 15:18:20 plunky Exp $"); 34 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> 45 46 #include "sdpquery.h" 47 48 typedef struct { 49 uint16_t id; 50 const char * desc; 51 void (*print)(sdp_data_t *); 52 } attr_t; 53 54 typedef struct { 55 uint16_t class; 56 const char * desc; 57 attr_t * attrs; 58 size_t nattr; 59 } service_t; 60 61 typedef struct { 62 uint16_t base; 63 const char * codeset; 64 } language_t; 65 66 static const char *string_uuid(uuid_t *); 67 static const char *string_vis(int, const char *, size_t); 68 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 *); 74 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 *); 88 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 *); 114 static void print_character_repertoires(sdp_data_t *); 115 116 static void print_rfcomm(sdp_data_t *); 117 static void print_bnep(sdp_data_t *); 118 static void print_avctp(sdp_data_t *); 119 static void print_avdtp(sdp_data_t *); 120 static void print_l2cap(sdp_data_t *); 121 122 attr_t protocol_list[] = { 123 { 0x0001, "SDP", NULL }, 124 { 0x0002, "UDP", NULL }, 125 { 0x0003, "RFCOMM", print_rfcomm }, 126 { 0x0004, "TCP", NULL }, 127 { 0x0005, "TCS_BIN", NULL }, 128 { 0x0006, "TCS_AT", NULL }, 129 { 0x0008, "OBEX", NULL }, 130 { 0x0009, "IP", NULL }, 131 { 0x000a, "FTP", NULL }, 132 { 0x000c, "HTTP", NULL }, 133 { 0x000e, "WSP", NULL }, 134 { 0x000f, "BNEP", print_bnep }, 135 { 0x0010, "UPNP", NULL }, 136 { 0x0011, "HIDP", NULL }, 137 { 0x0012, "HARDCOPY_CONTROL_CHANNEL", NULL }, 138 { 0x0014, "HARDCOPY_DATA_CHANNEL", NULL }, 139 { 0x0016, "HARDCOPY_NOTIFICATION", NULL }, 140 { 0x0017, "AVCTP", print_avctp }, 141 { 0x0019, "AVDTP", print_avdtp }, 142 { 0x001b, "CMTP", NULL }, 143 { 0x001d, "UDI_C_PLANE", NULL }, 144 { 0x001e, "MCAP_CONTROL_CHANNEL", NULL }, 145 { 0x001f, "MCAP_DATA_CHANNEL", NULL }, 146 { 0x0100, "L2CAP", print_l2cap }, 147 }; 148 149 attr_t universal_attrs[] = { 150 { 0x0000, "ServiceRecordHandle", print_uint32x }, 151 { 0x0001, "ServiceClassIDList", print_service_class_id_list }, 152 { 0x0002, "ServiceRecordState", print_uint32x }, 153 { 0x0003, "ServiceID", print_uuid }, 154 { 0x0004, "ProtocolDescriptorList", print_protocol_descriptor_list }, 155 { 0x0005, "BrowseGroupList", print_uuid_list }, 156 { 0x0006, "LanguageBaseAttributeIDList", print_language_base_attribute_id_list }, 157 { 0x0007, "ServiceInfoTimeToLive", print_uint32d }, 158 { 0x0008, "ServiceAvailability", print_service_availability }, 159 { 0x0009, "BluetoothProfileDescriptorList", print_bluetooth_profile_descriptor_list }, 160 { 0x000a, "DocumentationURL", print_url }, 161 { 0x000b, "ClientExecutableURL", print_url }, 162 { 0x000c, "IconURL", print_url }, 163 { 0x000d, "AdditionalProtocolDescriptorLists", print_additional_protocol_descriptor_lists }, 164 }; 165 166 attr_t language_attrs[] = { /* Language Attribute Offsets */ 167 { 0x0000, "ServiceName", print_language_string }, 168 { 0x0001, "ServiceDescription", print_language_string }, 169 { 0x0002, "ProviderName", print_language_string }, 170 }; 171 172 attr_t sds_attrs[] = { /* Service Discovery Server */ 173 { 0x0200, "VersionNumberList", print_sds_version_number_list }, 174 { 0x0201, "ServiceDatabaseState", print_uint32x }, 175 }; 176 177 attr_t bgd_attrs[] = { /* Browse Group Descriptor */ 178 { 0x0200, "GroupID", print_uuid }, 179 }; 180 181 attr_t ct_attrs[] = { /* Cordless Telephony */ 182 { 0x0301, "ExternalNetwork", print_ct_network }, 183 }; 184 185 attr_t asrc_attrs[] = { /* Audio Source */ 186 { 0x0311, "SupportedFeatures", print_asrc_features }, 187 }; 188 189 attr_t asink_attrs[] = { /* Audio Sink */ 190 { 0x0311, "SupportedFeatures", print_asink_features }, 191 }; 192 193 attr_t avrcp_attrs[] = { /* Audio Video Remote Control Profile */ 194 { 0x0311, "SupportedFeatures", print_avrcp_features }, 195 }; 196 197 attr_t lan_attrs[] = { /* LAN Access Using PPP */ 198 { 0x0200, "IPSubnet", print_string }, 199 }; 200 201 attr_t dun_attrs[] = { /* Dialup Networking */ 202 { 0x0305, "AudioFeedbackSupport", print_bool }, 203 }; 204 205 attr_t irmc_sync_attrs[] = { /* IrMC Sync */ 206 { 0x0301, "SupportedDataStoresList", print_supported_data_stores }, 207 }; 208 209 attr_t opush_attrs[] = { /* Object Push */ 210 { 0x0303, "SupportedFormatsList", print_supported_formats }, 211 }; 212 213 attr_t hset_attrs[] = { /* Headset */ 214 { 0x0302, "RemoteAudioVolumeControl", print_bool }, 215 }; 216 217 attr_t fax_attrs[] = { /* Fax */ 218 { 0x0302, "FAXClass1", print_bool }, 219 { 0x0303, "FAXClass2.0", print_bool }, 220 { 0x0304, "FAXClass2", print_bool }, 221 { 0x0305, "AudioFeedbackSupport", print_bool }, 222 }; 223 224 attr_t panu_attrs[] = { /* Personal Area Networking User */ 225 { 0x030a, "SecurityDescription", print_security_description }, 226 }; 227 228 attr_t nap_attrs[] = { /* Network Access Point */ 229 { 0x030a, "SecurityDescription", print_security_description }, 230 { 0x030b, "NetAccessType", print_net_access_type }, 231 { 0x030c, "MaxNetAccessRate", print_uint32d }, 232 { 0x030d, "IPv4Subnet", print_string }, 233 { 0x030e, "IPv6Subnet", print_string }, 234 }; 235 236 attr_t gn_attrs[] = { /* Group Network */ 237 { 0x030a, "SecurityDescription", print_security_description }, 238 { 0x030d, "IPv4Subnet", print_string }, 239 { 0x030e, "IPv6Subnet", print_string }, 240 }; 241 242 attr_t bp_attrs[] = { /* Basic Printing */ 243 { 0x0350, "DocumentFormatsSupported", print_string }, 244 { 0x0352, "CharacterRepertoiresSupported", print_character_repertoires }, 245 { 0x0354, "XHTML-PrintImageFormatsSupported", print_string }, 246 { 0x0356, "ColorSupported", print_bool }, 247 { 0x0358, "1284ID", print_string }, 248 { 0x035a, "PrinterName", print_string }, 249 { 0x035c, "PrinterLocation", print_string }, 250 { 0x035e, "DuplexSupported", print_bool }, 251 { 0x0360, "MediaTypesSupported", print_string }, 252 { 0x0362, "MaxMediaWidth", print_uint16d }, 253 { 0x0364, "MaxMediaLength", print_uint16d }, 254 { 0x0366, "EnhancedLayoutSupport", print_bool }, 255 { 0x0368, "RUIFormatsSupported", print_string }, 256 { 0x0370, "ReferencePrintingRUISupported", print_bool }, 257 { 0x0372, "DirectPrintingRUISupported", print_bool }, 258 { 0x0374, "ReferencePrintingTopURL", print_url }, 259 { 0x0376, "DirectPrintingTopURL", print_url }, 260 { 0x037a, "DeviceName", print_string }, 261 }; 262 263 attr_t hf_attrs[] = { /* Handsfree */ 264 { 0x0311, "SupportedFeatures", print_hf_features }, 265 }; 266 267 attr_t hfag_attrs[] = { /* Handsfree Audio Gateway */ 268 { 0x0301, "Network", print_hfag_network }, 269 { 0x0311, "SupportedFeatures", print_hfag_features }, 270 }; 271 272 attr_t rui_attrs[] = { /* Reflected User Interface */ 273 { 0x0368, "RUIFormatsSupported", print_string }, 274 { 0x0378, "PrinterAdminRUITopURL", print_url }, 275 }; 276 277 attr_t hid_attrs[] = { /* Human Interface Device */ 278 { 0x0200, "HIDDeviceReleaseNumber", print_hid_version }, 279 { 0x0201, "HIDParserVersion", print_hid_version }, 280 { 0x0202, "HIDDeviceSubClass", print_hid_device_subclass }, 281 { 0x0203, "HIDCountryCode", print_uint8x }, 282 { 0x0204, "HIDVirtualCable", print_bool }, 283 { 0x0205, "HIDReconnectInitiate", print_bool }, 284 { 0x0206, "HIDDescriptorList", print_hid_descriptor_list }, 285 { 0x0207, "HIDLANGIDBaseList", NULL }, 286 { 0x0208, "HIDSDPDisable", print_bool }, 287 { 0x0209, "HIDBatteryPower", print_bool }, 288 { 0x020a, "HIDRemoteWake", print_bool }, 289 { 0x020b, "HIDProfileVersion", print_profile_version }, 290 { 0x020c, "HIDSupervisionTimeout", print_uint16d }, 291 { 0x020d, "HIDNormallyConnectable", print_bool }, 292 { 0x020e, "HIDBootDevice", print_bool }, 293 }; 294 295 attr_t pnp_attrs[] = { /* Device ID */ 296 { 0x0200, "SpecificationID", print_profile_version }, 297 { 0x0201, "VendorID", print_uint16x }, 298 { 0x0202, "ProductID", print_uint16x }, 299 { 0x0203, "Version", print_hid_version }, 300 { 0x0204, "PrimaryRecord", print_bool }, 301 { 0x0205, "VendorIDSource", print_pnp_source }, 302 }; 303 304 attr_t mas_attrs[] = { /* Message Access Server */ 305 { 0x0315, "InstanceID", print_uint8d }, 306 { 0x0316, "SupportedMessageTypes", print_mas_types }, 307 }; 308 309 attr_t pse_attrs[] = { /* Phonebook Access Server */ 310 { 0x0314, "SupportedRepositories", print_supported_repositories }, 311 }; 312 313 #define A(a) a, __arraycount(a) 314 service_t service_list[] = { 315 { 0x1000, "Service Discovery Server", A(sds_attrs) }, 316 { 0x1001, "Browse Group Descriptor", A(bgd_attrs) }, 317 { 0x1002, "Public Browse Root", NULL, 0 }, 318 { 0x1101, "Serial Port", NULL, 0 }, 319 { 0x1102, "LAN Access Using PPP", A(lan_attrs) }, 320 { 0x1103, "Dialup Networking", A(dun_attrs) }, 321 { 0x1104, "IrMC Sync", A(irmc_sync_attrs) }, 322 { 0x1105, "Object Push", A(opush_attrs) }, 323 { 0x1106, "File Transfer", NULL, 0 }, 324 { 0x1107, "IrMC Sync Command", NULL, 0 }, 325 { 0x1108, "Headset", A(hset_attrs) }, 326 { 0x1109, "Cordless Telephony", A(ct_attrs) }, 327 { 0x110a, "Audio Source", A(asrc_attrs) }, 328 { 0x110b, "Audio Sink", A(asink_attrs) }, 329 { 0x110c, "A/V Remote Control Target", A(avrcp_attrs) }, 330 { 0x110d, "Advanced Audio Distribution", NULL, 0 }, 331 { 0x110e, "A/V Remote Control", A(avrcp_attrs) }, 332 { 0x110f, "Video Conferencing", NULL, 0 }, 333 { 0x1110, "Intercom", NULL, 0 }, 334 { 0x1111, "Fax", A(fax_attrs) }, 335 { 0x1112, "Headset Audio Gateway", NULL, 0 }, 336 { 0x1113, "WAP", NULL, 0 }, 337 { 0x1114, "WAP Client", NULL, 0 }, 338 { 0x1115, "Personal Area Networking User", A(panu_attrs) }, 339 { 0x1116, "Network Access Point", A(nap_attrs) }, 340 { 0x1117, "Group Network", A(gn_attrs) }, 341 { 0x1118, "Direct Printing", NULL, 0 }, 342 { 0x1119, "Reference Printing", A(bp_attrs) }, 343 { 0x111a, "Imaging", NULL, 0 }, 344 { 0x111b, "Imaging Responder", NULL, 0 }, 345 { 0x111c, "Imaging Automatic Archive", NULL, 0 }, 346 { 0x111d, "Imaging Referenced Objects", NULL, 0 }, 347 { 0x111e, "Handsfree", A(hf_attrs) }, 348 { 0x111f, "Handsfree Audio Gateway", A(hfag_attrs) }, 349 { 0x1120, "Direct Printing Reference Objects", NULL, 0 }, 350 { 0x1121, "Reflected User Interface", A(rui_attrs) }, 351 { 0x1122, "Basic Printing", NULL, 0 }, 352 { 0x1123, "Printing Status", NULL, 0 }, 353 { 0x1124, "Human Interface Device", A(hid_attrs) }, 354 { 0x1125, "Hardcopy Cable Replacement", NULL, 0 }, 355 { 0x1126, "Hardcopy Cable Replacement Print", NULL, 0 }, 356 { 0x1127, "Hardcopy Cable Replacement Scan", NULL, 0 }, 357 { 0x1128, "Common ISDN Access", NULL, 0 }, 358 { 0x1129, "Video Conferencing GW", NULL, 0 }, 359 { 0x112a, "UDI MT", NULL, 0 }, 360 { 0x112b, "UDI TA", NULL, 0 }, 361 { 0x112c, "Audio/Video", NULL, 0 }, 362 { 0x112d, "SIM Access", NULL, 0 }, 363 { 0x112e, "Phonebook Access Client", NULL, 0 }, 364 { 0x112f, "Phonebook Access Server", A(pse_attrs) }, 365 { 0x1130, "Phonebook Access", NULL, 0 }, 366 { 0x1131, "Headset HS", NULL, 0 }, 367 { 0x1132, "Message Access Server", A(mas_attrs) }, 368 { 0x1133, "Message Notification Server", NULL, 0 }, 369 { 0x1134, "Message Access Profile", NULL, 0 }, 370 { 0x1200, "PNP Information", A(pnp_attrs) }, 371 { 0x1201, "Generic Networking", NULL, 0 }, 372 { 0x1202, "Generic File Transfer", NULL, 0 }, 373 { 0x1203, "Generic Audio", NULL, 0 }, 374 { 0x1204, "Generic Telephony", NULL, 0 }, 375 { 0x1205, "UPNP", NULL, 0 }, 376 { 0x1206, "UPNP IP", NULL, 0 }, 377 { 0x1300, "UPNP IP PAN", NULL, 0 }, 378 { 0x1301, "UPNP IP LAP", NULL, 0 }, 379 { 0x1302, "UPNP IP L2CAP", NULL, 0 }, 380 { 0x1303, "Video Source", NULL, 0 }, 381 { 0x1304, "Video Sink", NULL, 0 }, 382 { 0x1305, "Video Distribution", NULL, 0 }, 383 { 0x1400, "HDP", NULL, 0 }, 384 { 0x1401, "HDP Source", NULL, 0 }, 385 { 0x1402, "HDP Sink", NULL, 0 }, 386 }; 387 #undef A 388 389 /* extracted Service Class ID List */ 390 #define MAX_SERVICES 16 391 static size_t nservices; 392 static uint16_t service_class[MAX_SERVICES]; 393 394 /* extracted Language Base Attribute ID List */ 395 #define MAX_LANGUAGES 16 396 static int nlanguages; 397 static language_t language[MAX_LANGUAGES]; 398 static int current; 399 400 static bool 401 sdp_get_uint8(sdp_data_t *d, uint8_t *vp) 402 { 403 uintmax_t v; 404 405 if (sdp_data_type(d) != SDP_DATA_UINT8 406 || !sdp_get_uint(d, &v)) 407 return false; 408 409 *vp = (uint8_t)v; 410 return true; 411 } 412 413 static bool 414 sdp_get_uint16(sdp_data_t *d, uint16_t *vp) 415 { 416 uintmax_t v; 417 418 if (sdp_data_type(d) != SDP_DATA_UINT16 419 || !sdp_get_uint(d, &v)) 420 return false; 421 422 *vp = (uint16_t)v; 423 return true; 424 } 425 426 static bool 427 sdp_get_uint32(sdp_data_t *d, uint32_t *vp) 428 { 429 uintmax_t v; 430 431 if (sdp_data_type(d) != SDP_DATA_UINT32 432 || !sdp_get_uint(d, &v)) 433 return false; 434 435 *vp = (uint32_t)v; 436 return true; 437 } 438 439 void 440 print_record(sdp_data_t *rec) 441 { 442 sdp_data_t value; 443 uint16_t id; 444 445 nservices = 0; 446 nlanguages = 0; 447 current = -1; 448 449 while (sdp_get_attr(rec, &id, &value)) { 450 if (Xflag) { 451 printf("AttributeID 0x%04x:\n", id); 452 print_hexdump(" ", value.next, value.end - value.next); 453 } else if (Rflag) { 454 printf("AttributeID 0x%04x:\n", id); 455 sdp_data_print(&value, 4); 456 } else if (print_universal_attribute(id, &value) 457 || print_language_attribute(id, &value) 458 || print_service_attribute(id, &value)) { 459 if (value.next != value.end) 460 printf(" [additional data ignored]\n"); 461 } else { 462 printf("AttributeID 0x%04x:\n", id); 463 sdp_data_print(&value, 4); 464 } 465 } 466 } 467 468 static const char * 469 string_uuid(uuid_t *uuid) 470 { 471 static char buf[64]; 472 const char *desc; 473 uuid_t u; 474 size_t i; 475 476 u = *uuid; 477 u.time_low = 0; 478 if (!uuid_equal(&u, &BLUETOOTH_BASE_UUID, NULL)) { 479 snprintf(buf, sizeof(buf), 480 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 481 uuid->time_low, uuid->time_mid, uuid->time_hi_and_version, 482 uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low, 483 uuid->node[0], uuid->node[1], uuid->node[2], 484 uuid->node[3], uuid->node[4], uuid->node[5]); 485 486 return buf; 487 } 488 489 desc = NULL; 490 for (i = 0; i < __arraycount(service_list); i++) { 491 if (uuid->time_low == service_list[i].class) { 492 desc = service_list[i].desc; 493 break; 494 } 495 } 496 497 for (i = 0; i < __arraycount(protocol_list); i++) { 498 if (uuid->time_low == protocol_list[i].id) { 499 desc = protocol_list[i].desc; 500 break; 501 } 502 } 503 504 if (!Nflag && desc) { 505 snprintf(buf, sizeof(buf), "%s", desc); 506 return buf; 507 } 508 509 snprintf(buf, sizeof(buf), "%s%s(0x%*.*x)", 510 (desc == NULL ? "" : desc), 511 (desc == NULL ? "" : " "), 512 (uuid->time_low > UINT16_MAX ? 8 : 4), 513 (uuid->time_low > UINT16_MAX ? 8 : 4), 514 uuid->time_low); 515 516 return buf; 517 } 518 519 static const char * 520 string_vis(int style, const char *src, size_t len) 521 { 522 static char buf[50]; 523 char *dst = buf; 524 525 style |= VIS_NL; 526 while (len > 0 && (dst + 5) < (buf + sizeof(buf))) { 527 dst = vis(dst, src[0], style, (len > 1 ? src[1] : 0)); 528 src++; 529 len--; 530 } 531 532 return buf; 533 } 534 535 static void 536 print_hexdump(const char *title, const uint8_t *data, size_t len) 537 { 538 int n, i; 539 540 i = 0; 541 n = printf("%s", title); 542 543 while (len-- > 0) { 544 if (++i > 8) { 545 printf("\n%*s", n, ""); 546 i = 1; 547 } 548 549 printf(" 0x%02x", *data++); 550 } 551 552 printf("\n"); 553 } 554 555 static bool 556 print_attribute(uint16_t id, sdp_data_t *value, attr_t *attr, int count) 557 { 558 int i; 559 560 for (i = 0; i < count; i++) { 561 if (id == attr[i].id) { 562 printf("%s", attr[i].desc); 563 564 if (Nflag) { 565 printf(" ("); 566 567 if (current != -1) 568 printf("0x%04x + ", language[current].base); 569 570 printf("0x%04x)", id); 571 } 572 573 printf(": "); 574 575 if (attr[i].print == NULL) { 576 printf("\n"); 577 sdp_data_print(value, 4); 578 value->next = value->end; 579 } else { 580 (attr[i].print)(value); 581 } 582 583 return true; 584 } 585 } 586 587 return false; 588 } 589 590 static bool 591 print_universal_attribute(uint16_t id, sdp_data_t *value) 592 { 593 594 return print_attribute(id, value, 595 universal_attrs, __arraycount(universal_attrs)); 596 } 597 598 static bool 599 print_language_attribute(uint16_t id, sdp_data_t *value) 600 { 601 bool done = false; 602 603 for (current = 0; current < nlanguages && !done; current++) 604 done = print_attribute(id - language[current].base, value, 605 language_attrs, __arraycount(language_attrs)); 606 607 current = -1; 608 return done; 609 } 610 611 static bool 612 print_service_attribute(uint16_t id, sdp_data_t *value) 613 { 614 size_t i, j; 615 616 for (i = 0; i < nservices; i++) { 617 for (j = 0; j < __arraycount(service_list); j++) { 618 if (service_class[i] == service_list[j].class) 619 return print_attribute(id, value, 620 service_list[j].attrs, 621 service_list[j].nattr); 622 } 623 } 624 625 return false; 626 } 627 628 static void 629 print_bool(sdp_data_t *data) 630 { 631 bool v; 632 633 if (!sdp_get_bool(data, &v)) 634 return; 635 636 printf("%s\n", (v ? "true" : "false")); 637 } 638 639 static void 640 print_uint8d(sdp_data_t *data) 641 { 642 uint8_t v; 643 644 if (!sdp_get_uint8(data, &v)) 645 return; 646 647 printf("%d\n", v); 648 } 649 650 static void 651 print_uint8x(sdp_data_t *data) 652 { 653 uint8_t v; 654 655 if (!sdp_get_uint8(data, &v)) 656 return; 657 658 printf("0x%02x\n", v); 659 } 660 661 static void 662 print_uint16d(sdp_data_t *data) 663 { 664 uint16_t v; 665 666 if (!sdp_get_uint16(data, &v)) 667 return; 668 669 printf("%d\n", v); 670 } 671 672 static void 673 print_uint16x(sdp_data_t *data) 674 { 675 uint16_t v; 676 677 if (!sdp_get_uint16(data, &v)) 678 return; 679 680 printf("0x%04x\n", v); 681 } 682 683 static void 684 print_uint32x(sdp_data_t *data) 685 { 686 uint32_t v; 687 688 if (!sdp_get_uint32(data, &v)) 689 return; 690 691 printf("0x%08x\n", v); 692 } 693 694 static void 695 print_uint32d(sdp_data_t *data) 696 { 697 uint32_t v; 698 699 if (!sdp_get_uint32(data, &v)) 700 return; 701 702 printf("%d\n", v); 703 } 704 705 static void 706 print_uuid(sdp_data_t *data) 707 { 708 uuid_t uuid; 709 710 if (!sdp_get_uuid(data, &uuid)) 711 return; 712 713 printf("%s\n", string_uuid(&uuid)); 714 } 715 716 static void 717 print_uuid_list(sdp_data_t *data) 718 { 719 sdp_data_t seq; 720 uuid_t uuid; 721 722 if (!sdp_get_seq(data, &seq)) 723 return; 724 725 printf("\n"); 726 while (sdp_get_uuid(&seq, &uuid)) 727 printf(" %s\n", string_uuid(&uuid)); 728 729 if (seq.next != seq.end) 730 printf(" [additional data]\n"); 731 } 732 733 static void 734 print_string(sdp_data_t *data) 735 { 736 char *str; 737 size_t len; 738 739 if (!sdp_get_str(data, &str, &len)) 740 return; 741 742 printf("\"%s\"\n", string_vis(VIS_CSTYLE, str, len)); 743 } 744 745 static void 746 print_url(sdp_data_t *data) 747 { 748 char *url; 749 size_t len; 750 751 if (!sdp_get_url(data, &url, &len)) 752 return; 753 754 printf("\"%s\"\n", string_vis(VIS_HTTPSTYLE, url, len)); 755 } 756 757 static void 758 print_profile_version(sdp_data_t *data) 759 { 760 uint16_t v; 761 762 if (!sdp_get_uint16(data, &v)) 763 return; 764 765 printf("v%d.%d\n", (v >> 8), (v & 0xff)); 766 } 767 768 /* 769 * This should only be called through print_language_attribute() which 770 * sets codeset of the string to be printed. 771 */ 772 static void 773 print_language_string(sdp_data_t *data) 774 { 775 char buf[50], *dst, *src; 776 iconv_t ih; 777 size_t n, srcleft, dstleft; 778 779 if (!sdp_get_str(data, &src, &srcleft)) 780 return; 781 782 dst = buf; 783 dstleft = sizeof(buf); 784 785 ih = iconv_open(nl_langinfo(CODESET), language[current].codeset); 786 if (ih == (iconv_t)-1) { 787 printf("Can't convert %s string\n", language[current].codeset); 788 return; 789 } 790 791 n = iconv(ih, (const char **)&src, &srcleft, &dst, &dstleft); 792 793 iconv_close(ih); 794 795 if (Nflag || n > 0) 796 printf("(%s) ", language[current].codeset); 797 798 printf("\"%.*s%s\n", (int)(sizeof(buf) - dstleft), buf, 799 (srcleft > 0 ? " ..." : "\"")); 800 } 801 802 static void 803 print_service_class_id_list(sdp_data_t *data) 804 { 805 sdp_data_t seq; 806 uuid_t uuid; 807 808 if (!sdp_get_seq(data, &seq)) 809 return; 810 811 printf("\n"); 812 while (sdp_get_uuid(&seq, &uuid)) { 813 printf(" %s\n", string_uuid(&uuid)); 814 815 if (nservices < MAX_SERVICES) { 816 service_class[nservices] = uuid.time_low; 817 uuid.time_low = 0; 818 if (uuid_equal(&uuid, &BLUETOOTH_BASE_UUID, NULL)) 819 nservices++; 820 } 821 } 822 823 if (seq.next != seq.end) 824 printf(" [additional data]\n"); 825 } 826 827 static void 828 print_protocol_descriptor(sdp_data_t *data) 829 { 830 uuid_t u0, uuid; 831 size_t i; 832 833 if (!sdp_get_uuid(data, &uuid)) 834 return; 835 836 u0 = uuid; 837 u0.time_low = 0; 838 if (uuid_equal(&u0, &BLUETOOTH_BASE_UUID, NULL)) { 839 for (i = 0; i < __arraycount(protocol_list); i++) { 840 if (uuid.time_low == protocol_list[i].id) { 841 printf(" %s", protocol_list[i].desc); 842 843 if (Nflag) 844 printf(" (0x%04x)", protocol_list[i].id); 845 846 if (protocol_list[i].print) 847 (protocol_list[i].print)(data); 848 849 if (data->next != data->end) 850 printf(" [additional data ignored]"); 851 852 printf("\n"); 853 return; 854 } 855 } 856 } 857 858 printf(" %s\n", string_uuid(&uuid)); 859 sdp_data_print(data, 4); 860 data->next = data->end; 861 } 862 863 static void 864 print_protocol_descriptor_list(sdp_data_t *data) 865 { 866 sdp_data_t seq, proto; 867 868 printf("\n"); 869 sdp_get_alt(data, data); /* strip [optional] alt header */ 870 871 while (sdp_get_seq(data, &seq)) 872 while (sdp_get_seq(&seq, &proto)) 873 print_protocol_descriptor(&proto); 874 } 875 876 static void 877 print_language_base_attribute_id_list(sdp_data_t *data) 878 { 879 sdp_data_t list; 880 uint16_t v; 881 const char *codeset; 882 char lang[2]; 883 884 if (!sdp_get_seq(data, &list)) 885 return; 886 887 printf("\n"); 888 while (list.next < list.end) { 889 /* 890 * ISO-639-1 natural language values are published at 891 * http://www.loc.gov/standards/iso639-2/php/code-list.php 892 */ 893 if (!sdp_get_uint16(&list, &v)) 894 break; 895 896 be16enc(lang, v); 897 if (!islower((int)lang[0]) || !islower((int)lang[1])) 898 break; 899 900 /* 901 * MIBenum values are published at 902 * http://www.iana.org/assignments/character-sets 903 */ 904 if (!sdp_get_uint16(&list, &v)) 905 break; 906 907 switch(v) { 908 case 3: codeset = "US-ASCII"; break; 909 case 4: codeset = "ISO-8859-1"; break; 910 case 5: codeset = "ISO-8859-2"; break; 911 case 106: codeset = "UTF-8"; break; 912 case 1013: codeset = "UTF-16BE"; break; 913 case 1014: codeset = "UTF-16LE"; break; 914 default: codeset = "Unknown"; break; 915 } 916 917 if (!sdp_get_uint16(&list, &v)) 918 break; 919 920 printf(" %.2s.%s base 0x%04x\n", lang, codeset, v); 921 922 if (nlanguages < MAX_LANGUAGES) { 923 language[nlanguages].base = v; 924 language[nlanguages].codeset = codeset; 925 nlanguages++; 926 } 927 } 928 929 if (list.next != list.end) 930 printf(" [additional data]\n"); 931 } 932 933 static void 934 print_service_availability(sdp_data_t *data) 935 { 936 uint8_t v; 937 938 if (!sdp_get_uint8(data, &v)) 939 return; 940 941 printf("%d/%d\n", v, UINT8_MAX); 942 } 943 944 static void 945 print_bluetooth_profile_descriptor_list(sdp_data_t *data) 946 { 947 sdp_data_t seq, profile; 948 uuid_t uuid; 949 uint16_t v; 950 951 if (!sdp_get_seq(data, &seq)) 952 return; 953 954 printf("\n"); 955 while (seq.next < seq.end) { 956 if (!sdp_get_seq(&seq, &profile) 957 || !sdp_get_uuid(&profile, &uuid) 958 || !sdp_get_uint16(&profile, &v)) 959 break; 960 961 printf(" %s, v%d.%d", string_uuid(&uuid), 962 (v >> 8), (v & 0xff)); 963 964 if (profile.next != profile.end) 965 printf(" [additional profile data]"); 966 967 printf("\n"); 968 } 969 970 if (seq.next != seq.end) 971 printf(" [additional data]\n"); 972 } 973 974 static void 975 print_additional_protocol_descriptor_lists(sdp_data_t *data) 976 { 977 sdp_data_t seq, stack, proto; 978 979 printf("\n"); 980 sdp_get_seq(data, &seq); 981 982 while (sdp_get_seq(&seq, &stack)) 983 while (sdp_get_seq(&stack, &proto)) 984 print_protocol_descriptor(&proto); 985 986 if (seq.next != seq.end) 987 printf(" [additional data]\n"); 988 } 989 990 static void 991 print_sds_version_number_list(sdp_data_t *data) 992 { 993 sdp_data_t list; 994 const char *sep; 995 uint16_t v; 996 997 if (!sdp_get_seq(data, &list)) 998 return; 999 1000 sep = ""; 1001 while (sdp_get_uint16(&list, &v)) { 1002 printf("%sv%d.%d", sep, (v >> 8), (v & 0xff)); 1003 sep = ", "; 1004 } 1005 1006 if (list.next != list.end) 1007 printf(" [additional data]"); 1008 1009 printf("\n"); 1010 } 1011 1012 static void 1013 print_ct_network(sdp_data_t *data) 1014 { 1015 uint8_t v; 1016 1017 if (!sdp_get_uint8(data, &v)) 1018 return; 1019 1020 switch (v) { 1021 case 0x01: printf("PSTN"); break; 1022 case 0x02: printf("ISDN"); break; 1023 case 0x03: printf("GSM"); break; 1024 case 0x04: printf("CDMA"); break; 1025 case 0x05: printf("Analogue Cellular"); break; 1026 case 0x06: printf("Packet Switched"); break; 1027 case 0x07: printf("Other"); break; 1028 default: printf("0x%02x", v); break; 1029 } 1030 1031 printf("\n"); 1032 } 1033 1034 static void 1035 print_asrc_features(sdp_data_t *data) 1036 { 1037 uint16_t v; 1038 1039 if (!sdp_get_uint16(data, &v)) 1040 return; 1041 1042 if (Nflag) 1043 printf("(0x%04x)", v); 1044 1045 printf("\n"); 1046 if (v & (1<<0)) printf(" Player\n"); 1047 if (v & (1<<1)) printf(" Microphone\n"); 1048 if (v & (1<<2)) printf(" Tuner\n"); 1049 if (v & (1<<3)) printf(" Mixer\n"); 1050 } 1051 1052 static void 1053 print_asink_features(sdp_data_t *data) 1054 { 1055 uint16_t v; 1056 1057 if (!sdp_get_uint16(data, &v)) 1058 return; 1059 1060 if (Nflag) 1061 printf("(0x%04x)", v); 1062 1063 printf("\n"); 1064 if (v & (1<<0)) printf(" Headphone\n"); 1065 if (v & (1<<1)) printf(" Speaker\n"); 1066 if (v & (1<<2)) printf(" Recorder\n"); 1067 if (v & (1<<3)) printf(" Amplifier\n"); 1068 } 1069 1070 static void 1071 print_avrcp_features(sdp_data_t *data) 1072 { 1073 uint16_t v; 1074 1075 if (!sdp_get_uint16(data, &v)) 1076 return; 1077 1078 if (Nflag) 1079 printf("(0x%04x)", v); 1080 1081 printf("\n"); 1082 if (v & (1<<0)) printf(" Category 1\n"); 1083 if (v & (1<<1)) printf(" Category 2\n"); 1084 if (v & (1<<2)) printf(" Category 3\n"); 1085 if (v & (1<<3)) printf(" Category 4\n"); 1086 } 1087 1088 static void 1089 print_supported_data_stores(sdp_data_t *data) 1090 { 1091 sdp_data_t list; 1092 const char *sep; 1093 uint8_t v; 1094 1095 if (!sdp_get_seq(data, &list)) 1096 return; 1097 1098 sep = "\n "; 1099 while (sdp_get_uint8(&list, &v)) { 1100 printf(sep); 1101 sep = ", "; 1102 1103 switch(v) { 1104 case 0x01: printf("Phonebook"); break; 1105 case 0x03: printf("Calendar"); break; 1106 case 0x05: printf("Notes"); break; 1107 case 0x06: printf("Messages"); break; 1108 default: printf("0x%02x", v); break; 1109 } 1110 } 1111 1112 if (list.next != list.end) 1113 printf(" [additional data]"); 1114 1115 printf("\n"); 1116 } 1117 1118 static void 1119 print_supported_formats(sdp_data_t *data) 1120 { 1121 sdp_data_t list; 1122 const char *sep; 1123 uint8_t v; 1124 1125 if (!sdp_get_seq(data, &list)) 1126 return; 1127 1128 sep = "\n "; 1129 while (sdp_get_uint8(&list, &v)) { 1130 printf(sep); 1131 sep = ", "; 1132 1133 switch(v) { 1134 case 0x01: printf("vCard 2.1"); break; 1135 case 0x02: printf("vCard 3.0"); break; 1136 case 0x03: printf("vCal 1.0"); break; 1137 case 0x04: printf("iCal 2.0"); break; 1138 case 0x05: printf("vNote"); break; 1139 case 0x06: printf("vMessage"); break; 1140 case 0xff: printf("Any"); break; 1141 default: printf("0x%02x", v); break; 1142 } 1143 } 1144 1145 if (list.next != list.end) 1146 printf(" [additional data]"); 1147 1148 printf("\n"); 1149 } 1150 1151 static void 1152 print_hid_version(sdp_data_t *data) 1153 { 1154 uint16_t v; 1155 1156 if (!sdp_get_uint16(data, &v)) 1157 return; 1158 1159 printf("v%d.%d.%d\n", 1160 ((v & 0xff00) >> 8), ((v & 0x00f0) >> 4), (v & 0x000f)); 1161 } 1162 1163 static void 1164 print_hid_device_subclass(sdp_data_t *data) 1165 { 1166 uint8_t v; 1167 1168 if (!sdp_get_uint8(data, &v)) 1169 return; 1170 1171 switch ((v & 0x3c) >> 2) { 1172 case 1: printf("Joystick"); break; 1173 case 2: printf("Gamepad"); break; 1174 case 3: printf("Remote Control"); break; 1175 case 4: printf("Sensing Device"); break; 1176 case 5: printf("Digitiser Tablet"); break; 1177 case 6: printf("Card Reader"); break; 1178 default: printf("Peripheral"); break; 1179 } 1180 1181 if (v & 0x40) printf(" <Keyboard>"); 1182 if (v & 0x80) printf(" <Mouse>"); 1183 1184 printf("\n"); 1185 } 1186 1187 static void 1188 print_hid_descriptor_list(sdp_data_t *data) 1189 { 1190 sdp_data_t list, seq; 1191 uint8_t type; 1192 const char *name; 1193 char *str; 1194 size_t len; 1195 1196 1197 if (!sdp_get_seq(data, &list)) 1198 return; 1199 1200 printf("\n"); 1201 while (list.next < list.end) { 1202 if (!sdp_get_seq(&list, &seq) 1203 || !sdp_get_uint8(&seq, &type) 1204 || !sdp_get_str(&seq, &str, &len)) 1205 return; 1206 1207 switch (type) { 1208 case 0x22: name = "Report"; break; 1209 case 0x23: name = "Physical Descriptor"; break; 1210 default: name = ""; break; 1211 } 1212 1213 printf(" Type 0x%02x: %s\n", type, name); 1214 print_hexdump(" Data", (uint8_t *)str, len); 1215 1216 if (seq.next != seq.end) 1217 printf(" [additional data]\n"); 1218 } 1219 } 1220 1221 static void 1222 print_security_description(sdp_data_t *data) 1223 { 1224 uint16_t v; 1225 1226 if (!sdp_get_uint16(data, &v)) 1227 return; 1228 1229 switch (v) { 1230 case 0x0000: printf("None"); break; 1231 case 0x0001: printf("Service-level Security"); break; 1232 case 0x0002: printf("802.1x Security"); break; 1233 default: printf("0x%04x", v); break; 1234 } 1235 1236 printf("\n"); 1237 } 1238 1239 static void 1240 print_hf_features(sdp_data_t *data) 1241 { 1242 uint16_t v; 1243 1244 if (!sdp_get_uint16(data, &v)) 1245 return; 1246 1247 if (Nflag) 1248 printf("(0x%04x)", v); 1249 1250 printf("\n"); 1251 if (v & (1<<0)) printf(" Echo Cancellation/Noise Reduction\n"); 1252 if (v & (1<<1)) printf(" Call Waiting\n"); 1253 if (v & (1<<2)) printf(" Caller Line Identification\n"); 1254 if (v & (1<<3)) printf(" Voice Recognition\n"); 1255 if (v & (1<<4)) printf(" Volume Control\n"); 1256 } 1257 1258 static void 1259 print_hfag_network(sdp_data_t *data) 1260 { 1261 uint8_t v; 1262 1263 if (!sdp_get_uint8(data, &v)) 1264 return; 1265 1266 switch (v) { 1267 case 0x01: printf("Ability to reject a call"); break; 1268 case 0x02: printf("No ability to reject a call"); break; 1269 default: printf("0x%02x", v); break; 1270 } 1271 1272 printf("\n"); 1273 } 1274 1275 static void 1276 print_hfag_features(sdp_data_t *data) 1277 { 1278 uint16_t v; 1279 1280 if (!sdp_get_uint16(data, &v)) 1281 return; 1282 1283 if (Nflag) 1284 printf("(0x%04x)", v); 1285 1286 printf("\n"); 1287 if (v & (1<<0)) printf(" 3 Way Calling\n"); 1288 if (v & (1<<1)) printf(" Echo Cancellation/Noise Reduction\n"); 1289 if (v & (1<<2)) printf(" Voice Recognition\n"); 1290 if (v & (1<<3)) printf(" In-band Ring Tone\n"); 1291 if (v & (1<<4)) printf(" Voice Tags\n"); 1292 } 1293 1294 static void 1295 print_net_access_type(sdp_data_t *data) 1296 { 1297 uint16_t v; 1298 1299 if (!sdp_get_uint16(data, &v)) 1300 return; 1301 1302 switch(v) { 1303 case 0x0000: printf("PSTN"); break; 1304 case 0x0001: printf("ISDN"); break; 1305 case 0x0002: printf("DSL"); break; 1306 case 0x0003: printf("Cable Modem"); break; 1307 case 0x0004: printf("10Mb Ethernet"); break; 1308 case 0x0005: printf("100Mb Ethernet"); break; 1309 case 0x0006: printf("4Mb Token Ring"); break; 1310 case 0x0007: printf("16Mb Token Ring"); break; 1311 case 0x0008: printf("100Mb Token Ring"); break; 1312 case 0x0009: printf("FDDI"); break; 1313 case 0x000a: printf("GSM"); break; 1314 case 0x000b: printf("CDMA"); break; 1315 case 0x000c: printf("GPRS"); break; 1316 case 0x000d: printf("3G Cellular"); break; 1317 case 0xfffe: printf("other"); break; 1318 default: printf("0x%04x", v); break; 1319 } 1320 1321 printf("\n"); 1322 } 1323 1324 static void 1325 print_pnp_source(sdp_data_t *data) 1326 { 1327 uint16_t v; 1328 1329 if (!sdp_get_uint16(data, &v)) 1330 return; 1331 1332 switch (v) { 1333 case 0x0001: printf("Bluetooth SIG"); break; 1334 case 0x0002: printf("USB Implementers Forum"); break; 1335 default: printf("0x%04x", v); break; 1336 } 1337 1338 printf("\n"); 1339 } 1340 1341 static void 1342 print_mas_types(sdp_data_t *data) 1343 { 1344 uint8_t v; 1345 1346 if (!sdp_get_uint8(data, &v)) 1347 return; 1348 1349 if (Nflag) 1350 printf("(0x%02x)", v); 1351 1352 printf("\n"); 1353 if (v & (1<<0)) printf(" EMAIL\n"); 1354 if (v & (1<<1)) printf(" SMS_GSM\n"); 1355 if (v & (1<<2)) printf(" SMS_CDMA\n"); 1356 if (v & (1<<3)) printf(" MMS\n"); 1357 } 1358 1359 static void 1360 print_supported_repositories(sdp_data_t *data) 1361 { 1362 uint8_t v; 1363 1364 if (!sdp_get_uint8(data, &v)) 1365 return; 1366 1367 if (Nflag) 1368 printf("(0x%02x)", v); 1369 1370 printf("\n"); 1371 if (v & (1<<0)) printf(" Local Phonebook\n"); 1372 if (v & (1<<1)) printf(" SIM Card\n"); 1373 } 1374 1375 static void 1376 print_character_repertoires(sdp_data_t *data) 1377 { 1378 uintmax_t v; 1379 1380 /* 1381 * we have no uint128 type so use uintmax as only 1382 * only 17-bits are currently defined, and if the 1383 * value is out of bounds it will be printed anyway 1384 */ 1385 if (sdp_data_type(data) != SDP_DATA_UINT128 1386 || !sdp_get_uint(data, &v)) 1387 return; 1388 1389 if (Nflag) 1390 printf("(0x%016jx)", v); 1391 1392 printf("\n"); 1393 if (v & (1<< 0)) printf(" ISO-8859-1\n"); 1394 if (v & (1<< 1)) printf(" ISO-8859-2\n"); 1395 if (v & (1<< 2)) printf(" ISO-8859-3\n"); 1396 if (v & (1<< 3)) printf(" ISO-8859-4\n"); 1397 if (v & (1<< 4)) printf(" ISO-8859-5\n"); 1398 if (v & (1<< 5)) printf(" ISO-8859-6\n"); 1399 if (v & (1<< 6)) printf(" ISO-8859-7\n"); 1400 if (v & (1<< 7)) printf(" ISO-8859-8\n"); 1401 if (v & (1<< 8)) printf(" ISO-8859-9\n"); 1402 if (v & (1<< 9)) printf(" ISO-8859-10\n"); 1403 if (v & (1<<10)) printf(" ISO-8859-13\n"); 1404 if (v & (1<<11)) printf(" ISO-8859-14\n"); 1405 if (v & (1<<12)) printf(" ISO-8859-15\n"); 1406 if (v & (1<<13)) printf(" GB18030\n"); 1407 if (v & (1<<14)) printf(" JIS X0208-1990, JIS X0201-1976\n"); 1408 if (v & (1<<15)) printf(" KSC 5601-1992\n"); 1409 if (v & (1<<16)) printf(" Big5\n"); 1410 if (v & (1<<17)) printf(" TIS-620\n"); 1411 } 1412 1413 static void 1414 print_rfcomm(sdp_data_t *data) 1415 { 1416 uint8_t v; 1417 1418 if (sdp_get_uint8(data, &v)) 1419 printf(" (channel %d)", v); 1420 } 1421 1422 static void 1423 print_bnep(sdp_data_t *data) 1424 { 1425 sdp_data_t seq; 1426 uint16_t v; 1427 const char *sep; 1428 1429 if (!sdp_get_uint16(data, &v) 1430 || !sdp_get_seq(data, &seq)) 1431 return; 1432 1433 printf(" (v%d.%d", (v >> 8), (v & 0xff)); 1434 sep = "; "; 1435 while (sdp_get_uint16(&seq, &v)) { 1436 printf(sep); 1437 sep = ", "; 1438 1439 switch (v) { 1440 case 0x0800: printf("IPv4"); break; 1441 case 0x0806: printf("ARP"); break; 1442 case 0x8100: printf("802.1Q"); break; 1443 case 0x86dd: printf("IPv6"); break; 1444 default: printf("0x%04x", v); break; 1445 } 1446 } 1447 printf(")"); 1448 1449 if (seq.next != seq.end) 1450 printf(" [additional data]"); 1451 } 1452 1453 static void 1454 print_avctp(sdp_data_t *data) 1455 { 1456 uint16_t v; 1457 1458 if (sdp_get_uint16(data, &v)) 1459 printf(" (v%d.%d)", (v >> 8), (v & 0xff)); 1460 } 1461 1462 static void 1463 print_avdtp(sdp_data_t *data) 1464 { 1465 uint16_t v; 1466 1467 if (sdp_get_uint16(data, &v)) 1468 printf(" (v%d.%d)", (v >> 8), (v & 0xff)); 1469 } 1470 1471 static void 1472 print_l2cap(sdp_data_t *data) 1473 { 1474 uint16_t v; 1475 1476 if (sdp_get_uint16(data, &v)) 1477 printf(" (PSM 0x%04x)", v); 1478 } 1479