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