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