print.c revision 1.13 1 /* $NetBSD: print.c,v 1.13 2011/06/24 20:53:56 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.13 2011/06/24 20:53:56 plunky Exp $");
34
35 #include <ctype.h>
36 #include <iconv.h>
37 #include <langinfo.h>
38 #include <sdp.h>
39 #include <stdbool.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <uuid.h>
44 #include <vis.h>
45
46 #include "sdpquery.h"
47
48 typedef struct {
49 uint16_t id;
50 const char * desc;
51 void (*print)(sdp_data_t *);
52 } attr_t;
53
54 typedef struct {
55 uint16_t class;
56 const char * desc;
57 attr_t * attrs;
58 size_t nattr;
59 } service_t;
60
61 typedef struct {
62 uint16_t base;
63 const char * codeset;
64 } language_t;
65
66 static const char *string_uuid(uuid_t *);
67 static const char *string_vis(int, const char *, size_t);
68
69 static void print_hexdump(const char *, const uint8_t *, size_t);
70 static bool print_attribute(uint16_t, sdp_data_t *, attr_t *, int);
71 static bool print_universal_attribute(uint16_t, sdp_data_t *);
72 static bool print_language_attribute(uint16_t, sdp_data_t *);
73 static bool print_service_attribute(uint16_t, sdp_data_t *);
74
75 static void print_bool(sdp_data_t *);
76 static void print_uint8d(sdp_data_t *);
77 static void print_uint8x(sdp_data_t *);
78 static void print_uint16d(sdp_data_t *);
79 static void print_uint16x(sdp_data_t *);
80 static void print_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, value.end - value.next);
485 } else if (Rflag) {
486 printf("AttributeID 0x%04x:\n", id);
487 sdp_data_print(&value, 4);
488 } else if (print_universal_attribute(id, &value)
489 || print_language_attribute(id, &value)
490 || print_service_attribute(id, &value)) {
491 if (value.next != value.end)
492 printf(" [additional data ignored]\n");
493 } else {
494 printf("AttributeID 0x%04x:\n", id);
495 sdp_data_print(&value, 4);
496 }
497 }
498 }
499
500 static const char *
501 string_uuid(uuid_t *uuid)
502 {
503 static char buf[64];
504 const char *desc;
505 uuid_t u;
506 size_t i;
507
508 u = *uuid;
509 u.time_low = 0;
510 if (!uuid_equal(&u, &BLUETOOTH_BASE_UUID, NULL)) {
511 snprintf(buf, sizeof(buf),
512 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
513 uuid->time_low, uuid->time_mid, uuid->time_hi_and_version,
514 uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low,
515 uuid->node[0], uuid->node[1], uuid->node[2],
516 uuid->node[3], uuid->node[4], uuid->node[5]);
517
518 return buf;
519 }
520
521 desc = NULL;
522 for (i = 0; i < __arraycount(service_list); i++) {
523 if (uuid->time_low == service_list[i].class) {
524 desc = service_list[i].desc;
525 break;
526 }
527 }
528
529 for (i = 0; i < __arraycount(protocol_list); i++) {
530 if (uuid->time_low == protocol_list[i].id) {
531 desc = protocol_list[i].desc;
532 break;
533 }
534 }
535
536 if (!Nflag && desc) {
537 snprintf(buf, sizeof(buf), "%s", desc);
538 return buf;
539 }
540
541 snprintf(buf, sizeof(buf), "%s%s(0x%*.*x)",
542 (desc == NULL ? "" : desc),
543 (desc == NULL ? "" : " "),
544 (uuid->time_low > UINT16_MAX ? 8 : 4),
545 (uuid->time_low > UINT16_MAX ? 8 : 4),
546 uuid->time_low);
547
548 return buf;
549 }
550
551 static const char *
552 string_vis(int style, const char *src, size_t len)
553 {
554 static char buf[50];
555 char *dst = buf;
556
557 style |= VIS_NL;
558 while (len > 0 && (dst + 5) < (buf + sizeof(buf))) {
559 dst = vis(dst, src[0], style, (len > 1 ? src[1] : 0));
560 src++;
561 len--;
562 }
563
564 return buf;
565 }
566
567 static void
568 print_hexdump(const char *title, const uint8_t *data, size_t len)
569 {
570 int n, i;
571
572 i = 0;
573 n = printf("%s", title);
574
575 while (len-- > 0) {
576 if (++i > 8) {
577 printf("\n%*s", n, "");
578 i = 1;
579 }
580
581 printf(" 0x%02x", *data++);
582 }
583
584 printf("\n");
585 }
586
587 static bool
588 print_attribute(uint16_t id, sdp_data_t *value, attr_t *attr, int count)
589 {
590 int i;
591
592 for (i = 0; i < count; i++) {
593 if (id == attr[i].id) {
594 printf("%s", attr[i].desc);
595
596 if (Nflag) {
597 printf(" (");
598
599 if (current != -1)
600 printf("0x%04x + ", language[current].base);
601
602 printf("0x%04x)", id);
603 }
604
605 printf(": ");
606
607 if (attr[i].print == NULL) {
608 printf("\n");
609 sdp_data_print(value, 4);
610 value->next = value->end;
611 } else {
612 (attr[i].print)(value);
613 }
614
615 return true;
616 }
617 }
618
619 return false;
620 }
621
622 static bool
623 print_universal_attribute(uint16_t id, sdp_data_t *value)
624 {
625
626 return print_attribute(id, value,
627 universal_attrs, __arraycount(universal_attrs));
628 }
629
630 static bool
631 print_language_attribute(uint16_t id, sdp_data_t *value)
632 {
633 bool done = false;
634
635 for (current = 0; current < nlanguages && !done; current++)
636 done = print_attribute(id - language[current].base, value,
637 language_attrs, __arraycount(language_attrs));
638
639 current = -1;
640 return done;
641 }
642
643 static bool
644 print_service_attribute(uint16_t id, sdp_data_t *value)
645 {
646 size_t i, j;
647
648 for (i = 0; i < nservices; i++) {
649 for (j = 0; j < __arraycount(service_list); j++) {
650 if (service_class[i] == service_list[j].class
651 && print_attribute(id, value,
652 service_list[j].attrs, service_list[j].nattr))
653 return true;
654 }
655 }
656
657 return false;
658 }
659
660 static void
661 print_bool(sdp_data_t *data)
662 {
663 bool v;
664
665 if (!sdp_get_bool(data, &v))
666 return;
667
668 printf("%s\n", (v ? "true" : "false"));
669 }
670
671 static void
672 print_uint8d(sdp_data_t *data)
673 {
674 uint8_t v;
675
676 if (!sdp_get_uint8(data, &v))
677 return;
678
679 printf("%d\n", v);
680 }
681
682 static void
683 print_uint8x(sdp_data_t *data)
684 {
685 uint8_t v;
686
687 if (!sdp_get_uint8(data, &v))
688 return;
689
690 printf("0x%02x\n", v);
691 }
692
693 static void
694 print_uint16d(sdp_data_t *data)
695 {
696 uint16_t v;
697
698 if (!sdp_get_uint16(data, &v))
699 return;
700
701 printf("%d\n", v);
702 }
703
704 static void
705 print_uint16x(sdp_data_t *data)
706 {
707 uint16_t v;
708
709 if (!sdp_get_uint16(data, &v))
710 return;
711
712 printf("0x%04x\n", v);
713 }
714
715 static void
716 print_uint32x(sdp_data_t *data)
717 {
718 uint32_t v;
719
720 if (!sdp_get_uint32(data, &v))
721 return;
722
723 printf("0x%08x\n", v);
724 }
725
726 static void
727 print_uint32d(sdp_data_t *data)
728 {
729 uint32_t v;
730
731 if (!sdp_get_uint32(data, &v))
732 return;
733
734 printf("%d\n", v);
735 }
736
737 static void
738 print_uuid(sdp_data_t *data)
739 {
740 uuid_t uuid;
741
742 if (!sdp_get_uuid(data, &uuid))
743 return;
744
745 printf("%s\n", string_uuid(&uuid));
746 }
747
748 static void
749 print_uuid_list(sdp_data_t *data)
750 {
751 sdp_data_t seq;
752 uuid_t uuid;
753
754 if (!sdp_get_seq(data, &seq))
755 return;
756
757 printf("\n");
758 while (sdp_get_uuid(&seq, &uuid))
759 printf(" %s\n", string_uuid(&uuid));
760
761 if (seq.next != seq.end)
762 printf(" [additional data]\n");
763 }
764
765 static void
766 print_string(sdp_data_t *data)
767 {
768 char *str;
769 size_t len;
770
771 if (!sdp_get_str(data, &str, &len))
772 return;
773
774 printf("\"%s\"\n", string_vis(VIS_CSTYLE, str, len));
775 }
776
777 static void
778 print_string_list(sdp_data_t *data)
779 {
780 char *str, *ep;
781 size_t len, l;
782
783 if (!sdp_get_str(data, &str, &len))
784 return;
785
786 printf("\n");
787 while (len > 0) {
788 ep = memchr(str, (int)',', len);
789 if (ep == NULL) {
790 l = len;
791 len = 0;
792 } else {
793 l = (size_t)(ep - str);
794 len -= l + 1;
795 ep++;
796 }
797 printf(" %s\n", string_vis(VIS_CSTYLE, str, l));
798 str = ep;
799 }
800 }
801
802 static void
803 print_url(sdp_data_t *data)
804 {
805 char *url;
806 size_t len;
807
808 if (!sdp_get_url(data, &url, &len))
809 return;
810
811 printf("\"%s\"\n", string_vis(VIS_HTTPSTYLE, url, len));
812 }
813
814 static void
815 print_profile_version(sdp_data_t *data)
816 {
817 uint16_t v;
818
819 if (!sdp_get_uint16(data, &v))
820 return;
821
822 printf("v%d.%d\n", (v >> 8), (v & 0xff));
823 }
824
825 /*
826 * This should only be called through print_language_attribute() which
827 * sets codeset of the string to be printed.
828 */
829 static void
830 print_language_string(sdp_data_t *data)
831 {
832 char buf[50], *dst, *src;
833 iconv_t ih;
834 size_t n, srcleft, dstleft;
835
836 if (!sdp_get_str(data, &src, &srcleft))
837 return;
838
839 dst = buf;
840 dstleft = sizeof(buf);
841
842 ih = iconv_open(nl_langinfo(CODESET), language[current].codeset);
843 if (ih == (iconv_t)-1) {
844 printf("Can't convert %s string\n", language[current].codeset);
845 return;
846 }
847
848 n = iconv(ih, (const char **)&src, &srcleft, &dst, &dstleft);
849
850 iconv_close(ih);
851
852 if (Nflag || n > 0)
853 printf("(%s) ", language[current].codeset);
854
855 printf("\"%.*s%s\n", (int)(sizeof(buf) - dstleft), buf,
856 (srcleft > 0 ? " ..." : "\""));
857 }
858
859 static void
860 print_service_class_id_list(sdp_data_t *data)
861 {
862 sdp_data_t seq;
863 uuid_t uuid;
864
865 if (!sdp_get_seq(data, &seq))
866 return;
867
868 printf("\n");
869 while (sdp_get_uuid(&seq, &uuid)) {
870 printf(" %s\n", string_uuid(&uuid));
871
872 if (nservices < MAX_SERVICES) {
873 service_class[nservices] = uuid.time_low;
874 uuid.time_low = 0;
875 if (uuid_equal(&uuid, &BLUETOOTH_BASE_UUID, NULL))
876 nservices++;
877 }
878 }
879
880 if (seq.next != seq.end)
881 printf(" [additional data]\n");
882 }
883
884 static void
885 print_protocol_descriptor(sdp_data_t *data)
886 {
887 uuid_t u0, uuid;
888 size_t i;
889
890 if (!sdp_get_uuid(data, &uuid))
891 return;
892
893 u0 = uuid;
894 u0.time_low = 0;
895 if (uuid_equal(&u0, &BLUETOOTH_BASE_UUID, NULL)) {
896 for (i = 0; i < __arraycount(protocol_list); i++) {
897 if (uuid.time_low == protocol_list[i].id) {
898 printf(" %s", protocol_list[i].desc);
899
900 if (Nflag)
901 printf(" (0x%04x)", protocol_list[i].id);
902
903 if (protocol_list[i].print)
904 (protocol_list[i].print)(data);
905
906 if (data->next != data->end)
907 printf(" [additional data ignored]");
908
909 printf("\n");
910 return;
911 }
912 }
913 }
914
915 printf(" %s\n", string_uuid(&uuid));
916 sdp_data_print(data, 4);
917 data->next = data->end;
918 }
919
920 static void
921 print_protocol_descriptor_list(sdp_data_t *data)
922 {
923 sdp_data_t seq, proto;
924
925 printf("\n");
926 sdp_get_alt(data, data); /* strip [optional] alt header */
927
928 while (sdp_get_seq(data, &seq))
929 while (sdp_get_seq(&seq, &proto))
930 print_protocol_descriptor(&proto);
931 }
932
933 static void
934 print_language_base_attribute_id_list(sdp_data_t *data)
935 {
936 sdp_data_t list;
937 uint16_t v;
938 const char *codeset;
939 char lang[2];
940
941 if (!sdp_get_seq(data, &list))
942 return;
943
944 printf("\n");
945 while (list.next < list.end) {
946 /*
947 * ISO-639-1 natural language values are published at
948 * http://www.loc.gov/standards/iso639-2/php/code-list.php
949 */
950 if (!sdp_get_uint16(&list, &v))
951 break;
952
953 be16enc(lang, v);
954 if (!islower((int)lang[0]) || !islower((int)lang[1]))
955 break;
956
957 /*
958 * MIBenum values are published at
959 * http://www.iana.org/assignments/character-sets
960 */
961 if (!sdp_get_uint16(&list, &v))
962 break;
963
964 switch(v) {
965 case 3: codeset = "US-ASCII"; break;
966 case 4: codeset = "ISO-8859-1"; break;
967 case 5: codeset = "ISO-8859-2"; break;
968 case 106: codeset = "UTF-8"; break;
969 case 1013: codeset = "UTF-16BE"; break;
970 case 1014: codeset = "UTF-16LE"; break;
971 default: codeset = "Unknown"; break;
972 }
973
974 if (!sdp_get_uint16(&list, &v))
975 break;
976
977 printf(" %.2s.%s base 0x%04x\n", lang, codeset, v);
978
979 if (nlanguages < MAX_LANGUAGES) {
980 language[nlanguages].base = v;
981 language[nlanguages].codeset = codeset;
982 nlanguages++;
983 }
984 }
985
986 if (list.next != list.end)
987 printf(" [additional data]\n");
988 }
989
990 static void
991 print_service_availability(sdp_data_t *data)
992 {
993 uint8_t v;
994
995 if (!sdp_get_uint8(data, &v))
996 return;
997
998 printf("%d/%d\n", v, UINT8_MAX);
999 }
1000
1001 static void
1002 print_bluetooth_profile_descriptor_list(sdp_data_t *data)
1003 {
1004 sdp_data_t seq, profile;
1005 uuid_t uuid;
1006 uint16_t v;
1007
1008 if (!sdp_get_seq(data, &seq))
1009 return;
1010
1011 printf("\n");
1012 while (seq.next < seq.end) {
1013 if (!sdp_get_seq(&seq, &profile)
1014 || !sdp_get_uuid(&profile, &uuid)
1015 || !sdp_get_uint16(&profile, &v))
1016 break;
1017
1018 printf(" %s, v%d.%d", string_uuid(&uuid),
1019 (v >> 8), (v & 0xff));
1020
1021 if (profile.next != profile.end)
1022 printf(" [additional profile data]");
1023
1024 printf("\n");
1025 }
1026
1027 if (seq.next != seq.end)
1028 printf(" [additional data]\n");
1029 }
1030
1031 static void
1032 print_additional_protocol_descriptor_lists(sdp_data_t *data)
1033 {
1034 sdp_data_t seq, stack, proto;
1035
1036 printf("\n");
1037 sdp_get_seq(data, &seq);
1038
1039 while (sdp_get_seq(&seq, &stack))
1040 while (sdp_get_seq(&stack, &proto))
1041 print_protocol_descriptor(&proto);
1042
1043 if (seq.next != seq.end)
1044 printf(" [additional data]\n");
1045 }
1046
1047 static void
1048 print_sds_version_number_list(sdp_data_t *data)
1049 {
1050 sdp_data_t list;
1051 const char *sep;
1052 uint16_t v;
1053
1054 if (!sdp_get_seq(data, &list))
1055 return;
1056
1057 sep = "";
1058 while (sdp_get_uint16(&list, &v)) {
1059 printf("%sv%d.%d", sep, (v >> 8), (v & 0xff));
1060 sep = ", ";
1061 }
1062
1063 if (list.next != list.end)
1064 printf(" [additional data]");
1065
1066 printf("\n");
1067 }
1068
1069 static void
1070 print_ct_network(sdp_data_t *data)
1071 {
1072 uint8_t v;
1073
1074 if (!sdp_get_uint8(data, &v))
1075 return;
1076
1077 switch (v) {
1078 case 0x01: printf("PSTN"); break;
1079 case 0x02: printf("ISDN"); break;
1080 case 0x03: printf("GSM"); break;
1081 case 0x04: printf("CDMA"); break;
1082 case 0x05: printf("Analogue Cellular"); break;
1083 case 0x06: printf("Packet Switched"); break;
1084 case 0x07: printf("Other"); break;
1085 default: printf("0x%02x", v); break;
1086 }
1087
1088 printf("\n");
1089 }
1090
1091 static void
1092 print_asrc_features(sdp_data_t *data)
1093 {
1094 uint16_t v;
1095
1096 if (!sdp_get_uint16(data, &v))
1097 return;
1098
1099 if (Nflag)
1100 printf("(0x%04x)", v);
1101
1102 printf("\n");
1103 if (v & (1<<0)) printf(" Player\n");
1104 if (v & (1<<1)) printf(" Microphone\n");
1105 if (v & (1<<2)) printf(" Tuner\n");
1106 if (v & (1<<3)) printf(" Mixer\n");
1107 }
1108
1109 static void
1110 print_asink_features(sdp_data_t *data)
1111 {
1112 uint16_t v;
1113
1114 if (!sdp_get_uint16(data, &v))
1115 return;
1116
1117 if (Nflag)
1118 printf("(0x%04x)", v);
1119
1120 printf("\n");
1121 if (v & (1<<0)) printf(" Headphone\n");
1122 if (v & (1<<1)) printf(" Speaker\n");
1123 if (v & (1<<2)) printf(" Recorder\n");
1124 if (v & (1<<3)) printf(" Amplifier\n");
1125 }
1126
1127 static void
1128 print_avrcp_features(sdp_data_t *data)
1129 {
1130 uint16_t v;
1131
1132 if (!sdp_get_uint16(data, &v))
1133 return;
1134
1135 if (Nflag)
1136 printf("(0x%04x)", v);
1137
1138 printf("\n");
1139 if (v & (1<<0)) printf(" Category 1\n");
1140 if (v & (1<<1)) printf(" Category 2\n");
1141 if (v & (1<<2)) printf(" Category 3\n");
1142 if (v & (1<<3)) printf(" Category 4\n");
1143 }
1144
1145 static void
1146 print_supported_data_stores(sdp_data_t *data)
1147 {
1148 sdp_data_t list;
1149 const char *sep;
1150 uint8_t v;
1151
1152 if (!sdp_get_seq(data, &list))
1153 return;
1154
1155 sep = "\n ";
1156 while (sdp_get_uint8(&list, &v)) {
1157 printf("%s", sep);
1158 sep = ", ";
1159
1160 switch(v) {
1161 case 0x01: printf("Phonebook"); break;
1162 case 0x03: printf("Calendar"); break;
1163 case 0x05: printf("Notes"); break;
1164 case 0x06: printf("Messages"); break;
1165 default: printf("0x%02x", v); break;
1166 }
1167 }
1168
1169 if (list.next != list.end)
1170 printf(" [additional data]");
1171
1172 printf("\n");
1173 }
1174
1175 static void
1176 print_supported_formats(sdp_data_t *data)
1177 {
1178 sdp_data_t list;
1179 const char *sep;
1180 uint8_t v;
1181
1182 if (!sdp_get_seq(data, &list))
1183 return;
1184
1185 sep = "\n ";
1186 while (sdp_get_uint8(&list, &v)) {
1187 printf("%s", sep);
1188 sep = ", ";
1189
1190 switch(v) {
1191 case 0x01: printf("vCard 2.1"); break;
1192 case 0x02: printf("vCard 3.0"); break;
1193 case 0x03: printf("vCal 1.0"); break;
1194 case 0x04: printf("iCal 2.0"); break;
1195 case 0x05: printf("vNote"); break;
1196 case 0x06: printf("vMessage"); break;
1197 case 0xff: printf("Any"); break;
1198 default: printf("0x%02x", v); break;
1199 }
1200 }
1201
1202 if (list.next != list.end)
1203 printf(" [additional data]");
1204
1205 printf("\n");
1206 }
1207
1208 static void
1209 print_hid_version(sdp_data_t *data)
1210 {
1211 uint16_t v;
1212
1213 if (!sdp_get_uint16(data, &v))
1214 return;
1215
1216 printf("v%d.%d.%d\n",
1217 ((v & 0xff00) >> 8), ((v & 0x00f0) >> 4), (v & 0x000f));
1218 }
1219
1220 static void
1221 print_hid_device_subclass(sdp_data_t *data)
1222 {
1223 uint8_t v;
1224
1225 if (!sdp_get_uint8(data, &v))
1226 return;
1227
1228 switch ((v & 0x3c) >> 2) {
1229 case 1: printf("Joystick"); break;
1230 case 2: printf("Gamepad"); break;
1231 case 3: printf("Remote Control"); break;
1232 case 4: printf("Sensing Device"); break;
1233 case 5: printf("Digitiser Tablet"); break;
1234 case 6: printf("Card Reader"); break;
1235 default: printf("Peripheral"); break;
1236 }
1237
1238 if (v & 0x40) printf(" <Keyboard>");
1239 if (v & 0x80) printf(" <Mouse>");
1240
1241 printf("\n");
1242 }
1243
1244 static void
1245 print_hid_descriptor_list(sdp_data_t *data)
1246 {
1247 sdp_data_t list, seq;
1248 uint8_t type;
1249 const char *name;
1250 char *str;
1251 size_t len;
1252
1253
1254 if (!sdp_get_seq(data, &list))
1255 return;
1256
1257 printf("\n");
1258 while (list.next < list.end) {
1259 if (!sdp_get_seq(&list, &seq)
1260 || !sdp_get_uint8(&seq, &type)
1261 || !sdp_get_str(&seq, &str, &len))
1262 return;
1263
1264 switch (type) {
1265 case 0x22: name = "Report"; break;
1266 case 0x23: name = "Physical Descriptor"; break;
1267 default: name = ""; break;
1268 }
1269
1270 printf(" Type 0x%02x: %s\n", type, name);
1271 print_hexdump(" Data", (uint8_t *)str, len);
1272
1273 if (seq.next != seq.end)
1274 printf(" [additional data]\n");
1275 }
1276 }
1277
1278 static void
1279 print_security_description(sdp_data_t *data)
1280 {
1281 uint16_t v;
1282
1283 if (!sdp_get_uint16(data, &v))
1284 return;
1285
1286 switch (v) {
1287 case 0x0000: printf("None"); break;
1288 case 0x0001: printf("Service-level Security"); break;
1289 case 0x0002: printf("802.1x Security"); break;
1290 default: printf("0x%04x", v); break;
1291 }
1292
1293 printf("\n");
1294 }
1295
1296 static void
1297 print_hf_features(sdp_data_t *data)
1298 {
1299 uint16_t v;
1300
1301 if (!sdp_get_uint16(data, &v))
1302 return;
1303
1304 if (Nflag)
1305 printf("(0x%04x)", v);
1306
1307 printf("\n");
1308 if (v & (1<<0)) printf(" Echo Cancellation/Noise Reduction\n");
1309 if (v & (1<<1)) printf(" Call Waiting\n");
1310 if (v & (1<<2)) printf(" Caller Line Identification\n");
1311 if (v & (1<<3)) printf(" Voice Recognition\n");
1312 if (v & (1<<4)) printf(" Volume Control\n");
1313 }
1314
1315 static void
1316 print_hfag_network(sdp_data_t *data)
1317 {
1318 uint8_t v;
1319
1320 if (!sdp_get_uint8(data, &v))
1321 return;
1322
1323 switch (v) {
1324 case 0x01: printf("Ability to reject a call"); break;
1325 case 0x02: printf("No ability to reject a call"); break;
1326 default: printf("0x%02x", v); break;
1327 }
1328
1329 printf("\n");
1330 }
1331
1332 static void
1333 print_hfag_features(sdp_data_t *data)
1334 {
1335 uint16_t v;
1336
1337 if (!sdp_get_uint16(data, &v))
1338 return;
1339
1340 if (Nflag)
1341 printf("(0x%04x)", v);
1342
1343 printf("\n");
1344 if (v & (1<<0)) printf(" 3 Way Calling\n");
1345 if (v & (1<<1)) printf(" Echo Cancellation/Noise Reduction\n");
1346 if (v & (1<<2)) printf(" Voice Recognition\n");
1347 if (v & (1<<3)) printf(" In-band Ring Tone\n");
1348 if (v & (1<<4)) printf(" Voice Tags\n");
1349 }
1350
1351 static void
1352 print_net_access_type(sdp_data_t *data)
1353 {
1354 uint16_t v;
1355
1356 if (!sdp_get_uint16(data, &v))
1357 return;
1358
1359 switch(v) {
1360 case 0x0000: printf("PSTN"); break;
1361 case 0x0001: printf("ISDN"); break;
1362 case 0x0002: printf("DSL"); break;
1363 case 0x0003: printf("Cable Modem"); break;
1364 case 0x0004: printf("10Mb Ethernet"); break;
1365 case 0x0005: printf("100Mb Ethernet"); break;
1366 case 0x0006: printf("4Mb Token Ring"); break;
1367 case 0x0007: printf("16Mb Token Ring"); break;
1368 case 0x0008: printf("100Mb Token Ring"); break;
1369 case 0x0009: printf("FDDI"); break;
1370 case 0x000a: printf("GSM"); break;
1371 case 0x000b: printf("CDMA"); break;
1372 case 0x000c: printf("GPRS"); break;
1373 case 0x000d: printf("3G Cellular"); break;
1374 case 0xfffe: printf("other"); break;
1375 default: printf("0x%04x", v); break;
1376 }
1377
1378 printf("\n");
1379 }
1380
1381 static void
1382 print_pnp_source(sdp_data_t *data)
1383 {
1384 uint16_t v;
1385
1386 if (!sdp_get_uint16(data, &v))
1387 return;
1388
1389 switch (v) {
1390 case 0x0001: printf("Bluetooth SIG"); break;
1391 case 0x0002: printf("USB Implementers Forum"); break;
1392 default: printf("0x%04x", v); break;
1393 }
1394
1395 printf("\n");
1396 }
1397
1398 static void
1399 print_mas_types(sdp_data_t *data)
1400 {
1401 uint8_t v;
1402
1403 if (!sdp_get_uint8(data, &v))
1404 return;
1405
1406 if (Nflag)
1407 printf("(0x%02x)", v);
1408
1409 printf("\n");
1410 if (v & (1<<0)) printf(" EMAIL\n");
1411 if (v & (1<<1)) printf(" SMS_GSM\n");
1412 if (v & (1<<2)) printf(" SMS_CDMA\n");
1413 if (v & (1<<3)) printf(" MMS\n");
1414 }
1415
1416 static void
1417 print_supported_repositories(sdp_data_t *data)
1418 {
1419 uint8_t v;
1420
1421 if (!sdp_get_uint8(data, &v))
1422 return;
1423
1424 if (Nflag)
1425 printf("(0x%02x)", v);
1426
1427 printf("\n");
1428 if (v & (1<<0)) printf(" Local Phonebook\n");
1429 if (v & (1<<1)) printf(" SIM Card\n");
1430 }
1431
1432 static void
1433 print_character_repertoires(sdp_data_t *data)
1434 {
1435 uintmax_t v;
1436
1437 /*
1438 * we have no uint128 type so use uintmax as only
1439 * only 17-bits are currently defined, and if the
1440 * value is out of bounds it will be printed anyway
1441 */
1442 if (sdp_data_type(data) != SDP_DATA_UINT128
1443 || !sdp_get_uint(data, &v))
1444 return;
1445
1446 if (Nflag)
1447 printf("(0x%016jx)", v);
1448
1449 printf("\n");
1450 if (v & (1<< 0)) printf(" ISO-8859-1\n");
1451 if (v & (1<< 1)) printf(" ISO-8859-2\n");
1452 if (v & (1<< 2)) printf(" ISO-8859-3\n");
1453 if (v & (1<< 3)) printf(" ISO-8859-4\n");
1454 if (v & (1<< 4)) printf(" ISO-8859-5\n");
1455 if (v & (1<< 5)) printf(" ISO-8859-6\n");
1456 if (v & (1<< 6)) printf(" ISO-8859-7\n");
1457 if (v & (1<< 7)) printf(" ISO-8859-8\n");
1458 if (v & (1<< 8)) printf(" ISO-8859-9\n");
1459 if (v & (1<< 9)) printf(" ISO-8859-10\n");
1460 if (v & (1<<10)) printf(" ISO-8859-13\n");
1461 if (v & (1<<11)) printf(" ISO-8859-14\n");
1462 if (v & (1<<12)) printf(" ISO-8859-15\n");
1463 if (v & (1<<13)) printf(" GB18030\n");
1464 if (v & (1<<14)) printf(" JIS X0208-1990, JIS X0201-1976\n");
1465 if (v & (1<<15)) printf(" KSC 5601-1992\n");
1466 if (v & (1<<16)) printf(" Big5\n");
1467 if (v & (1<<17)) printf(" TIS-620\n");
1468 }
1469
1470 static void
1471 print_bip_capabilities(sdp_data_t *data)
1472 {
1473 uint8_t v;
1474
1475 if (!sdp_get_uint8(data, &v))
1476 return;
1477
1478 if (Nflag)
1479 printf("(0x%02x)", v);
1480
1481 printf("\n");
1482 if (v & (1<< 0)) printf(" Generic imaging\n");
1483 if (v & (1<< 1)) printf(" Capturing\n");
1484 if (v & (1<< 2)) printf(" Printing\n");
1485 if (v & (1<< 3)) printf(" Displaying\n");
1486 }
1487
1488 static void
1489 print_bip_features(sdp_data_t *data)
1490 {
1491 uint16_t v;
1492
1493 if (!sdp_get_uint16(data, &v))
1494 return;
1495
1496 if (Nflag)
1497 printf("(0x%04x)", v);
1498
1499 printf("\n");
1500 if (v & (1<<0)) printf(" ImagePush\n");
1501 if (v & (1<<1)) printf(" ImagePush-Store\n");
1502 if (v & (1<<2)) printf(" ImagePush-Print\n");
1503 if (v & (1<<3)) printf(" ImagePush-Display\n");
1504 if (v & (1<<4)) printf(" ImagePull\n");
1505 if (v & (1<<5)) printf(" AdvancedImagePrinting\n");
1506 if (v & (1<<6)) printf(" AutomaticArchive\n");
1507 if (v & (1<<7)) printf(" RemoteCamera\n");
1508 if (v & (1<<8)) printf(" RemoteDisplay\n");
1509 }
1510
1511 static void
1512 print_bip_functions(sdp_data_t *data)
1513 {
1514 uint32_t v;
1515
1516 if (!sdp_get_uint32(data, &v))
1517 return;
1518
1519 if (Nflag)
1520 printf("(0x%08x)", v);
1521
1522 printf("\n");
1523 if (v & (1<< 0)) printf(" GetCapabilities\n");
1524 if (v & (1<< 1)) printf(" PutImage\n");
1525 if (v & (1<< 2)) printf(" PutLinkedAttachment\n");
1526 if (v & (1<< 3)) printf(" PutLinkedThumbnail\n");
1527 if (v & (1<< 4)) printf(" RemoteDisplay\n");
1528 if (v & (1<< 5)) printf(" GetImagesList\n");
1529 if (v & (1<< 6)) printf(" GetImageProperties\n");
1530 if (v & (1<< 7)) printf(" GetImage\n");
1531 if (v & (1<< 8)) printf(" GetLinkedThumbnail\n");
1532 if (v & (1<< 9)) printf(" GetLinkedAttachment\n");
1533 if (v & (1<<10)) printf(" DeleteImage\n");
1534 if (v & (1<<11)) printf(" StartPrint\n");
1535 if (v & (1<<12)) printf(" GetPartialImage\n");
1536 if (v & (1<<13)) printf(" StartArchive\n");
1537 if (v & (1<<14)) printf(" GetMonitoringImage\n");
1538 if (v & (1<<16)) printf(" GetStatus\n");
1539 }
1540
1541 static void
1542 print_bip_capacity(sdp_data_t *data)
1543 {
1544 char buf[9];
1545 uint64_t v;
1546
1547 if (!sdp_get_uint64(data, &v))
1548 return;
1549
1550 if (v > INT64_MAX) {
1551 printf("more than ");
1552 v = INT64_MAX;
1553 }
1554
1555 (void)humanize_number(buf, sizeof(buf), (int64_t)v,
1556 "bytes", HN_AUTOSCALE, HN_NOSPACE);
1557
1558 printf("%s\n", buf);
1559 }
1560
1561 static void
1562 print_rfcomm(sdp_data_t *data)
1563 {
1564 uint8_t v;
1565
1566 if (sdp_get_uint8(data, &v))
1567 printf(" (channel %d)", v);
1568 }
1569
1570 static void
1571 print_bnep(sdp_data_t *data)
1572 {
1573 sdp_data_t seq;
1574 uint16_t v;
1575 const char *sep;
1576
1577 if (!sdp_get_uint16(data, &v)
1578 || !sdp_get_seq(data, &seq))
1579 return;
1580
1581 printf(" (v%d.%d", (v >> 8), (v & 0xff));
1582 sep = "; ";
1583 while (sdp_get_uint16(&seq, &v)) {
1584 printf("%s", sep);
1585 sep = ", ";
1586
1587 switch (v) {
1588 case 0x0800: printf("IPv4"); break;
1589 case 0x0806: printf("ARP"); break;
1590 case 0x8100: printf("802.1Q"); break;
1591 case 0x86dd: printf("IPv6"); break;
1592 default: printf("0x%04x", v); break;
1593 }
1594 }
1595 printf(")");
1596
1597 if (seq.next != seq.end)
1598 printf(" [additional data]");
1599 }
1600
1601 static void
1602 print_avctp(sdp_data_t *data)
1603 {
1604 uint16_t v;
1605
1606 if (sdp_get_uint16(data, &v))
1607 printf(" (v%d.%d)", (v >> 8), (v & 0xff));
1608 }
1609
1610 static void
1611 print_avdtp(sdp_data_t *data)
1612 {
1613 uint16_t v;
1614
1615 if (sdp_get_uint16(data, &v))
1616 printf(" (v%d.%d)", (v >> 8), (v & 0xff));
1617 }
1618
1619 static void
1620 print_l2cap(sdp_data_t *data)
1621 {
1622 uint16_t v;
1623
1624 if (sdp_get_uint16(data, &v))
1625 printf(" (PSM 0x%04x)", v);
1626 }
1627