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