| |
| // SPDX-License-Identifier: GPL-2.0-or-later |
| /* |
| * |
| * BlueZ - Bluetooth protocol stack for Linux |
| * |
| * Copyright (C) 2020 Intel Corporation. All rights reserved. |
| * |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #define _GNU_SOURCE |
| #include <stdio.h> |
| #include <stdbool.h> |
| #include <inttypes.h> |
| #include <errno.h> |
| #include <unistd.h> |
| #include <stdlib.h> |
| #include <fcntl.h> |
| #include <string.h> |
| |
| #include "gdbus/gdbus.h" |
| |
| #include "src/shared/util.h" |
| #include "src/shared/shell.h" |
| #include "print.h" |
| |
| static void print_fixed_iter(const char *label, const char *name, |
| DBusMessageIter *iter) |
| { |
| dbus_bool_t *valbool; |
| dbus_uint32_t *valu32; |
| dbus_uint16_t *valu16; |
| dbus_int16_t *vals16; |
| unsigned char *byte; |
| int len; |
| |
| switch (dbus_message_iter_get_arg_type(iter)) { |
| case DBUS_TYPE_BOOLEAN: |
| dbus_message_iter_get_fixed_array(iter, &valbool, &len); |
| |
| if (len <= 0) |
| return; |
| |
| bt_shell_printf("%s%s:\n", label, name); |
| bt_shell_hexdump((void *)valbool, len * sizeof(*valbool)); |
| |
| break; |
| case DBUS_TYPE_UINT32: |
| dbus_message_iter_get_fixed_array(iter, &valu32, &len); |
| |
| if (len <= 0) |
| return; |
| |
| bt_shell_printf("%s%s:\n", label, name); |
| bt_shell_hexdump((void *)valu32, len * sizeof(*valu32)); |
| |
| break; |
| case DBUS_TYPE_UINT16: |
| dbus_message_iter_get_fixed_array(iter, &valu16, &len); |
| |
| if (len <= 0) |
| return; |
| |
| bt_shell_printf("%s%s:\n", label, name); |
| bt_shell_hexdump((void *)valu16, len * sizeof(*valu16)); |
| |
| break; |
| case DBUS_TYPE_INT16: |
| dbus_message_iter_get_fixed_array(iter, &vals16, &len); |
| |
| if (len <= 0) |
| return; |
| |
| bt_shell_printf("%s%s:\n", label, name); |
| bt_shell_hexdump((void *)vals16, len * sizeof(*vals16)); |
| |
| break; |
| case DBUS_TYPE_BYTE: |
| dbus_message_iter_get_fixed_array(iter, &byte, &len); |
| |
| if (len <= 0) |
| return; |
| |
| bt_shell_printf("%s%s:\n", label, name); |
| bt_shell_hexdump((void *)byte, len * sizeof(*byte)); |
| |
| break; |
| default: |
| return; |
| }; |
| } |
| |
| void print_iter(const char *label, const char *name, DBusMessageIter *iter) |
| { |
| dbus_bool_t valbool; |
| dbus_uint32_t valu32; |
| dbus_uint16_t valu16; |
| dbus_int16_t vals16; |
| unsigned char byte; |
| const char *valstr; |
| DBusMessageIter subiter; |
| char *entry; |
| |
| if (iter == NULL) { |
| bt_shell_printf("%s%s is nil\n", label, name); |
| return; |
| } |
| |
| switch (dbus_message_iter_get_arg_type(iter)) { |
| case DBUS_TYPE_INVALID: |
| bt_shell_printf("%s%s is invalid\n", label, name); |
| break; |
| case DBUS_TYPE_STRING: |
| case DBUS_TYPE_OBJECT_PATH: |
| dbus_message_iter_get_basic(iter, &valstr); |
| bt_shell_printf("%s%s: %s\n", label, name, valstr); |
| break; |
| case DBUS_TYPE_BOOLEAN: |
| dbus_message_iter_get_basic(iter, &valbool); |
| bt_shell_printf("%s%s: %s\n", label, name, |
| valbool == TRUE ? "yes" : "no"); |
| break; |
| case DBUS_TYPE_UINT32: |
| dbus_message_iter_get_basic(iter, &valu32); |
| bt_shell_printf("%s%s: 0x%08x (%d)\n", label, name, valu32, |
| valu32); |
| break; |
| case DBUS_TYPE_UINT16: |
| dbus_message_iter_get_basic(iter, &valu16); |
| bt_shell_printf("%s%s: 0x%04x (%d)\n", label, name, valu16, |
| valu16); |
| break; |
| case DBUS_TYPE_INT16: |
| dbus_message_iter_get_basic(iter, &vals16); |
| bt_shell_printf("%s%s: 0x%04x (%d)\n", label, name, vals16, |
| vals16); |
| break; |
| case DBUS_TYPE_BYTE: |
| dbus_message_iter_get_basic(iter, &byte); |
| bt_shell_printf("%s%s: 0x%02x (%d)\n", label, name, byte, byte); |
| break; |
| case DBUS_TYPE_VARIANT: |
| dbus_message_iter_recurse(iter, &subiter); |
| print_iter(label, name, &subiter); |
| break; |
| case DBUS_TYPE_ARRAY: |
| dbus_message_iter_recurse(iter, &subiter); |
| |
| if (dbus_type_is_fixed( |
| dbus_message_iter_get_arg_type(&subiter))) { |
| print_fixed_iter(label, name, &subiter); |
| break; |
| } |
| |
| while (dbus_message_iter_get_arg_type(&subiter) != |
| DBUS_TYPE_INVALID) { |
| print_iter(label, name, &subiter); |
| dbus_message_iter_next(&subiter); |
| } |
| break; |
| case DBUS_TYPE_DICT_ENTRY: |
| dbus_message_iter_recurse(iter, &subiter); |
| |
| if (dbus_message_iter_get_arg_type(&subiter) == |
| DBUS_TYPE_STRING) { |
| dbus_message_iter_get_basic(&subiter, &valstr); |
| entry = g_strconcat(name, ".", valstr, NULL); |
| } else { |
| entry = g_strconcat(name, ".Key", NULL); |
| print_iter(label, entry, &subiter); |
| g_free(entry); |
| |
| entry = g_strconcat(name, ".Value", NULL); |
| } |
| |
| dbus_message_iter_next(&subiter); |
| print_iter(label, entry, &subiter); |
| g_free(entry); |
| break; |
| default: |
| bt_shell_printf("%s%s has unsupported type\n", label, name); |
| break; |
| } |
| } |
| |
| void print_property_with_label(GDBusProxy *proxy, const char *name, |
| const char *label) |
| { |
| DBusMessageIter iter; |
| |
| if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE) |
| return; |
| |
| print_iter("\t", label ? label : name, &iter); |
| } |
| |
| void print_property(GDBusProxy *proxy, const char *name) |
| { |
| print_property_with_label(proxy, name, NULL); |
| } |