print.c revision 1.17 1 /* $NetBSD: print.c,v 1.17 2011/08/14 13:27:47 christos 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.17 2011/08/14 13:27:47 christos 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, (void *)&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