3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2012 Intel Corporation. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include "src/shared/shell.h"
38 #include "src/shared/util.h"
39 #include "gdbus/gdbus.h"
42 #include "advertising.h"
44 /* String display constants */
45 #define COLORED_NEW COLOR_GREEN "NEW" COLOR_OFF
46 #define COLORED_CHG COLOR_YELLOW "CHG" COLOR_OFF
47 #define COLORED_DEL COLOR_RED "DEL" COLOR_OFF
49 #define PROMPT_ON COLOR_BLUE "[bluetooth]" COLOR_OFF "# "
50 #define PROMPT_OFF "Waiting to connect to bluetoothd..."
52 static DBusConnection *dbus_conn;
54 static GDBusProxy *agent_manager;
55 static char *auto_register_agent = NULL;
63 static struct adapter *default_ctrl;
64 static GDBusProxy *default_dev;
65 static GDBusProxy *default_attr;
66 static GList *ctrl_list;
67 static GList *battery_proxies;
69 static const char *agent_arguments[] = {
80 static const char *ad_arguments[] = {
88 static void proxy_leak(gpointer data)
90 printf("Leaking proxy %p\n", data);
93 static void setup_standard_input(void)
95 bt_shell_attach(fileno(stdin));
98 static void connect_handler(DBusConnection *connection, void *user_data)
100 bt_shell_set_prompt(PROMPT_ON);
103 static void disconnect_handler(DBusConnection *connection, void *user_data)
107 bt_shell_set_prompt(PROMPT_OFF);
109 g_list_free_full(ctrl_list, proxy_leak);
110 g_list_free_full(battery_proxies, proxy_leak);
112 battery_proxies = NULL;
117 static void print_adapter(GDBusProxy *proxy, const char *description)
119 DBusMessageIter iter;
120 const char *address, *name;
122 if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE)
125 dbus_message_iter_get_basic(&iter, &address);
127 if (g_dbus_proxy_get_property(proxy, "Alias", &iter) == TRUE)
128 dbus_message_iter_get_basic(&iter, &name);
132 bt_shell_printf("%s%s%sController %s %s %s\n",
133 description ? "[" : "",
135 description ? "] " : "",
138 default_ctrl->proxy == proxy ?
143 static void print_device(GDBusProxy *proxy, const char *description)
145 DBusMessageIter iter;
146 const char *address, *name;
148 if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE)
151 dbus_message_iter_get_basic(&iter, &address);
153 if (g_dbus_proxy_get_property(proxy, "Alias", &iter) == TRUE)
154 dbus_message_iter_get_basic(&iter, &name);
158 bt_shell_printf("%s%s%sDevice %s %s\n",
159 description ? "[" : "",
161 description ? "] " : "",
165 static void print_fixed_iter(const char *label, const char *name,
166 DBusMessageIter *iter)
168 dbus_bool_t *valbool;
169 dbus_uint32_t *valu32;
170 dbus_uint16_t *valu16;
171 dbus_int16_t *vals16;
175 switch (dbus_message_iter_get_arg_type(iter)) {
176 case DBUS_TYPE_BOOLEAN:
177 dbus_message_iter_get_fixed_array(iter, &valbool, &len);
182 bt_shell_printf("%s%s:\n", label, name);
183 bt_shell_hexdump((void *)valbool, len * sizeof(*valbool));
186 case DBUS_TYPE_UINT32:
187 dbus_message_iter_get_fixed_array(iter, &valu32, &len);
192 bt_shell_printf("%s%s:\n", label, name);
193 bt_shell_hexdump((void *)valu32, len * sizeof(*valu32));
196 case DBUS_TYPE_UINT16:
197 dbus_message_iter_get_fixed_array(iter, &valu16, &len);
202 bt_shell_printf("%s%s:\n", label, name);
203 bt_shell_hexdump((void *)valu16, len * sizeof(*valu16));
206 case DBUS_TYPE_INT16:
207 dbus_message_iter_get_fixed_array(iter, &vals16, &len);
212 bt_shell_printf("%s%s:\n", label, name);
213 bt_shell_hexdump((void *)vals16, len * sizeof(*vals16));
217 dbus_message_iter_get_fixed_array(iter, &byte, &len);
222 bt_shell_printf("%s%s:\n", label, name);
223 bt_shell_hexdump((void *)byte, len * sizeof(*byte));
231 static void print_iter(const char *label, const char *name,
232 DBusMessageIter *iter)
235 dbus_uint32_t valu32;
236 dbus_uint16_t valu16;
240 DBusMessageIter subiter;
244 bt_shell_printf("%s%s is nil\n", label, name);
248 switch (dbus_message_iter_get_arg_type(iter)) {
249 case DBUS_TYPE_INVALID:
250 bt_shell_printf("%s%s is invalid\n", label, name);
252 case DBUS_TYPE_STRING:
253 case DBUS_TYPE_OBJECT_PATH:
254 dbus_message_iter_get_basic(iter, &valstr);
255 bt_shell_printf("%s%s: %s\n", label, name, valstr);
257 case DBUS_TYPE_BOOLEAN:
258 dbus_message_iter_get_basic(iter, &valbool);
259 bt_shell_printf("%s%s: %s\n", label, name,
260 valbool == TRUE ? "yes" : "no");
262 case DBUS_TYPE_UINT32:
263 dbus_message_iter_get_basic(iter, &valu32);
264 bt_shell_printf("%s%s: 0x%08x\n", label, name, valu32);
266 case DBUS_TYPE_UINT16:
267 dbus_message_iter_get_basic(iter, &valu16);
268 bt_shell_printf("%s%s: 0x%04x\n", label, name, valu16);
270 case DBUS_TYPE_INT16:
271 dbus_message_iter_get_basic(iter, &vals16);
272 bt_shell_printf("%s%s: %d\n", label, name, vals16);
275 dbus_message_iter_get_basic(iter, &byte);
276 bt_shell_printf("%s%s: 0x%02x (%d)\n", label, name, byte, byte);
278 case DBUS_TYPE_VARIANT:
279 dbus_message_iter_recurse(iter, &subiter);
280 print_iter(label, name, &subiter);
282 case DBUS_TYPE_ARRAY:
283 dbus_message_iter_recurse(iter, &subiter);
285 if (dbus_type_is_fixed(
286 dbus_message_iter_get_arg_type(&subiter))) {
287 print_fixed_iter(label, name, &subiter);
291 while (dbus_message_iter_get_arg_type(&subiter) !=
293 print_iter(label, name, &subiter);
294 dbus_message_iter_next(&subiter);
297 case DBUS_TYPE_DICT_ENTRY:
298 dbus_message_iter_recurse(iter, &subiter);
299 entry = g_strconcat(name, " Key", NULL);
300 print_iter(label, entry, &subiter);
303 entry = g_strconcat(name, " Value", NULL);
304 dbus_message_iter_next(&subiter);
305 print_iter(label, entry, &subiter);
309 bt_shell_printf("%s%s has unsupported type\n", label, name);
314 static void print_property_with_label(GDBusProxy *proxy, const char *name,
317 DBusMessageIter iter;
319 if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
322 print_iter("\t", label ? label : name, &iter);
325 static void print_property(GDBusProxy *proxy, const char *name)
327 print_property_with_label(proxy, name, NULL);
330 static void print_uuid(const char *uuid)
334 text = bt_uuidstr_to_str(uuid);
339 str[sizeof(str) - 1] = '\0';
341 n = snprintf(str, sizeof(str), "%s", text);
342 if (n > sizeof(str) - 1) {
343 str[sizeof(str) - 2] = '.';
344 str[sizeof(str) - 3] = '.';
345 if (str[sizeof(str) - 4] == ' ')
346 str[sizeof(str) - 4] = '.';
351 bt_shell_printf("\tUUID: %s%*c(%s)\n", str, 26 - n, ' ', uuid);
353 bt_shell_printf("\tUUID: %*c(%s)\n", 26, ' ', uuid);
356 static void print_uuids(GDBusProxy *proxy)
358 DBusMessageIter iter, value;
360 if (g_dbus_proxy_get_property(proxy, "UUIDs", &iter) == FALSE)
363 dbus_message_iter_recurse(&iter, &value);
365 while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
368 dbus_message_iter_get_basic(&value, &uuid);
372 dbus_message_iter_next(&value);
376 static gboolean device_is_child(GDBusProxy *device, GDBusProxy *master)
378 DBusMessageIter iter;
379 const char *adapter, *path;
384 if (g_dbus_proxy_get_property(device, "Adapter", &iter) == FALSE)
387 dbus_message_iter_get_basic(&iter, &adapter);
388 path = g_dbus_proxy_get_path(master);
390 if (!strcmp(path, adapter))
396 static gboolean service_is_child(GDBusProxy *service)
398 DBusMessageIter iter;
401 if (g_dbus_proxy_get_property(service, "Device", &iter) == FALSE)
404 dbus_message_iter_get_basic(&iter, &device);
409 return g_dbus_proxy_lookup(default_ctrl->devices, NULL, device,
410 "org.bluez.Device1") != NULL;
413 static struct adapter *find_parent(GDBusProxy *device)
417 for (list = g_list_first(ctrl_list); list; list = g_list_next(list)) {
418 struct adapter *adapter = list->data;
420 if (device_is_child(device, adapter->proxy) == TRUE)
426 static void set_default_device(GDBusProxy *proxy, const char *attribute)
429 DBusMessageIter iter;
439 if (!g_dbus_proxy_get_property(proxy, "Alias", &iter)) {
440 if (!g_dbus_proxy_get_property(proxy, "Address", &iter))
444 path = g_dbus_proxy_get_path(proxy);
446 dbus_message_iter_get_basic(&iter, &desc);
447 desc = g_strdup_printf(COLOR_BLUE "[%s%s%s]" COLOR_OFF "# ", desc,
448 attribute ? ":" : "",
449 attribute ? attribute + strlen(path) : "");
452 bt_shell_set_prompt(desc ? desc : PROMPT_ON);
456 static void battery_added(GDBusProxy *proxy)
458 battery_proxies = g_list_append(battery_proxies, proxy);
461 static void battery_removed(GDBusProxy *proxy)
463 battery_proxies = g_list_remove(battery_proxies, proxy);
466 static void device_added(GDBusProxy *proxy)
468 DBusMessageIter iter;
469 struct adapter *adapter = find_parent(proxy);
476 adapter->devices = g_list_append(adapter->devices, proxy);
477 print_device(proxy, COLORED_NEW);
478 bt_shell_set_env(g_dbus_proxy_get_path(proxy), proxy);
483 if (g_dbus_proxy_get_property(proxy, "Connected", &iter)) {
484 dbus_bool_t connected;
486 dbus_message_iter_get_basic(&iter, &connected);
489 set_default_device(proxy, NULL);
493 static struct adapter *find_ctrl(GList *source, const char *path);
495 static struct adapter *adapter_new(GDBusProxy *proxy)
497 struct adapter *adapter = g_malloc0(sizeof(struct adapter));
499 ctrl_list = g_list_append(ctrl_list, adapter);
502 default_ctrl = adapter;
507 static void adapter_added(GDBusProxy *proxy)
509 struct adapter *adapter;
510 adapter = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy));
512 adapter = adapter_new(proxy);
514 adapter->proxy = proxy;
516 print_adapter(proxy, COLORED_NEW);
517 bt_shell_set_env(g_dbus_proxy_get_path(proxy), proxy);
520 static void ad_manager_added(GDBusProxy *proxy)
522 struct adapter *adapter;
523 adapter = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy));
525 adapter = adapter_new(proxy);
527 adapter->ad_proxy = proxy;
530 static void proxy_added(GDBusProxy *proxy, void *user_data)
532 const char *interface;
534 interface = g_dbus_proxy_get_interface(proxy);
536 if (!strcmp(interface, "org.bluez.Device1")) {
538 } else if (!strcmp(interface, "org.bluez.Adapter1")) {
539 adapter_added(proxy);
540 } else if (!strcmp(interface, "org.bluez.AgentManager1")) {
541 if (!agent_manager) {
542 agent_manager = proxy;
544 if (auto_register_agent &&
545 !bt_shell_get_env("NON_INTERACTIVE"))
546 agent_register(dbus_conn, agent_manager,
547 auto_register_agent);
549 } else if (!strcmp(interface, "org.bluez.GattService1")) {
550 if (service_is_child(proxy))
551 gatt_add_service(proxy);
552 } else if (!strcmp(interface, "org.bluez.GattCharacteristic1")) {
553 gatt_add_characteristic(proxy);
554 } else if (!strcmp(interface, "org.bluez.GattDescriptor1")) {
555 gatt_add_descriptor(proxy);
556 } else if (!strcmp(interface, "org.bluez.GattManager1")) {
557 gatt_add_manager(proxy);
558 } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
559 ad_manager_added(proxy);
560 } else if (!strcmp(interface, "org.bluez.Battery1")) {
561 battery_added(proxy);
565 static void set_default_attribute(GDBusProxy *proxy)
569 default_attr = proxy;
571 path = g_dbus_proxy_get_path(proxy);
573 set_default_device(default_dev, path);
576 static void device_removed(GDBusProxy *proxy)
578 struct adapter *adapter = find_parent(proxy);
584 adapter->devices = g_list_remove(adapter->devices, proxy);
586 print_device(proxy, COLORED_DEL);
587 bt_shell_set_env(g_dbus_proxy_get_path(proxy), NULL);
589 if (default_dev == proxy)
590 set_default_device(NULL, NULL);
593 static void adapter_removed(GDBusProxy *proxy)
597 for (ll = g_list_first(ctrl_list); ll; ll = g_list_next(ll)) {
598 struct adapter *adapter = ll->data;
600 if (adapter->proxy == proxy) {
601 print_adapter(proxy, COLORED_DEL);
602 bt_shell_set_env(g_dbus_proxy_get_path(proxy), NULL);
604 if (default_ctrl && default_ctrl->proxy == proxy) {
606 set_default_device(NULL, NULL);
609 ctrl_list = g_list_remove_link(ctrl_list, ll);
610 g_list_free(adapter->devices);
618 static void proxy_removed(GDBusProxy *proxy, void *user_data)
620 const char *interface;
622 interface = g_dbus_proxy_get_interface(proxy);
624 if (!strcmp(interface, "org.bluez.Device1")) {
625 device_removed(proxy);
626 } else if (!strcmp(interface, "org.bluez.Adapter1")) {
627 adapter_removed(proxy);
628 } else if (!strcmp(interface, "org.bluez.AgentManager1")) {
629 if (agent_manager == proxy) {
630 agent_manager = NULL;
631 if (auto_register_agent)
632 agent_unregister(dbus_conn, NULL);
634 } else if (!strcmp(interface, "org.bluez.GattService1")) {
635 gatt_remove_service(proxy);
637 if (default_attr == proxy)
638 set_default_attribute(NULL);
639 } else if (!strcmp(interface, "org.bluez.GattCharacteristic1")) {
640 gatt_remove_characteristic(proxy);
642 if (default_attr == proxy)
643 set_default_attribute(NULL);
644 } else if (!strcmp(interface, "org.bluez.GattDescriptor1")) {
645 gatt_remove_descriptor(proxy);
647 if (default_attr == proxy)
648 set_default_attribute(NULL);
649 } else if (!strcmp(interface, "org.bluez.GattManager1")) {
650 gatt_remove_manager(proxy);
651 } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
652 ad_unregister(dbus_conn, NULL);
653 } else if (!strcmp(interface, "org.bluez.Battery1")) {
654 battery_removed(proxy);
658 static struct adapter *find_ctrl(GList *source, const char *path)
662 for (list = g_list_first(source); list; list = g_list_next(list)) {
663 struct adapter *adapter = list->data;
665 if (!strcasecmp(g_dbus_proxy_get_path(adapter->proxy), path))
672 static void property_changed(GDBusProxy *proxy, const char *name,
673 DBusMessageIter *iter, void *user_data)
675 const char *interface;
676 struct adapter *ctrl;
678 interface = g_dbus_proxy_get_interface(proxy);
680 if (!strcmp(interface, "org.bluez.Device1")) {
681 if (default_ctrl && device_is_child(proxy,
682 default_ctrl->proxy) == TRUE) {
683 DBusMessageIter addr_iter;
686 if (g_dbus_proxy_get_property(proxy, "Address",
687 &addr_iter) == TRUE) {
690 dbus_message_iter_get_basic(&addr_iter,
692 str = g_strdup_printf("[" COLORED_CHG
693 "] Device %s ", address);
697 if (strcmp(name, "Connected") == 0) {
698 dbus_bool_t connected;
700 dbus_message_iter_get_basic(iter, &connected);
702 if (connected && default_dev == NULL)
703 set_default_device(proxy, NULL);
704 else if (!connected && default_dev == proxy)
705 set_default_device(NULL, NULL);
708 print_iter(str, name, iter);
711 } else if (!strcmp(interface, "org.bluez.Adapter1")) {
712 DBusMessageIter addr_iter;
715 if (g_dbus_proxy_get_property(proxy, "Address",
716 &addr_iter) == TRUE) {
719 dbus_message_iter_get_basic(&addr_iter, &address);
720 str = g_strdup_printf("[" COLORED_CHG
721 "] Controller %s ", address);
725 print_iter(str, name, iter);
727 } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
728 DBusMessageIter addr_iter;
731 ctrl = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy));
735 if (g_dbus_proxy_get_property(ctrl->proxy, "Address",
736 &addr_iter) == TRUE) {
739 dbus_message_iter_get_basic(&addr_iter, &address);
740 str = g_strdup_printf("[" COLORED_CHG
746 print_iter(str, name, iter);
748 } else if (proxy == default_attr) {
751 str = g_strdup_printf("[" COLORED_CHG "] Attribute %s ",
752 g_dbus_proxy_get_path(proxy));
754 print_iter(str, name, iter);
759 static void message_handler(DBusConnection *connection,
760 DBusMessage *message, void *user_data)
762 bt_shell_printf("[SIGNAL] %s.%s\n", dbus_message_get_interface(message),
763 dbus_message_get_member(message));
766 static struct adapter *find_ctrl_by_address(GList *source, const char *address)
770 for (list = g_list_first(source); list; list = g_list_next(list)) {
771 struct adapter *adapter = list->data;
772 DBusMessageIter iter;
775 if (g_dbus_proxy_get_property(adapter->proxy,
776 "Address", &iter) == FALSE)
779 dbus_message_iter_get_basic(&iter, &str);
781 if (!strcasecmp(str, address))
788 static GDBusProxy *find_battery_by_path(GList *source, const char *path)
792 for (list = g_list_first(source); list; list = g_list_next(list)) {
793 GDBusProxy *proxy = list->data;
795 if (strcmp(g_dbus_proxy_get_path(proxy), path) == 0)
802 static GDBusProxy *find_proxy_by_address(GList *source, const char *address)
806 for (list = g_list_first(source); list; list = g_list_next(list)) {
807 GDBusProxy *proxy = list->data;
808 DBusMessageIter iter;
811 if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE)
814 dbus_message_iter_get_basic(&iter, &str);
816 if (!strcasecmp(str, address))
823 static gboolean check_default_ctrl(void)
826 bt_shell_printf("No default controller available\n");
833 static gboolean parse_argument(int argc, char *argv[], const char **arg_table,
834 const char *msg, dbus_bool_t *value,
839 if (!strcmp(argv[1], "help")) {
840 for (opt = arg_table; opt && *opt; opt++)
841 bt_shell_printf("%s\n", *opt);
842 bt_shell_noninteractive_quit(EXIT_SUCCESS);
846 if (!strcmp(argv[1], "on") || !strcmp(argv[1], "yes")) {
853 if (!strcmp(argv[1], "off") || !strcmp(argv[1], "no")) {
858 for (opt = arg_table; opt && *opt; opt++) {
859 if (strcmp(argv[1], *opt) == 0) {
866 bt_shell_printf("Invalid argument %s\n", argv[1]);
870 static void cmd_list(int argc, char *argv[])
874 for (list = g_list_first(ctrl_list); list; list = g_list_next(list)) {
875 struct adapter *adapter = list->data;
876 print_adapter(adapter->proxy, NULL);
879 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
882 static void cmd_show(int argc, char *argv[])
884 struct adapter *adapter;
885 DBusMessageIter iter;
888 if (argc < 2 || !strlen(argv[1])) {
889 if (check_default_ctrl() == FALSE)
890 return bt_shell_noninteractive_quit(EXIT_FAILURE);
892 adapter = default_ctrl;
894 adapter = find_ctrl_by_address(ctrl_list, argv[1]);
896 bt_shell_printf("Controller %s not available\n",
898 return bt_shell_noninteractive_quit(EXIT_FAILURE);
902 if (!g_dbus_proxy_get_property(adapter->proxy, "Address", &iter))
903 return bt_shell_noninteractive_quit(EXIT_FAILURE);
905 dbus_message_iter_get_basic(&iter, &address);
907 if (g_dbus_proxy_get_property(adapter->proxy, "AddressType", &iter)) {
910 dbus_message_iter_get_basic(&iter, &type);
912 bt_shell_printf("Controller %s (%s)\n", address, type);
914 bt_shell_printf("Controller %s\n", address);
917 print_property(adapter->proxy, "Name");
918 print_property(adapter->proxy, "Alias");
919 print_property(adapter->proxy, "Class");
920 print_property(adapter->proxy, "Powered");
921 print_property(adapter->proxy, "Discoverable");
922 print_property(adapter->proxy, "DiscoverableTimeout");
923 print_property(adapter->proxy, "Pairable");
924 print_uuids(adapter->proxy);
925 print_property(adapter->proxy, "Modalias");
926 print_property(adapter->proxy, "Discovering");
928 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
929 print_property(adapter->proxy, "Advertising");
932 if (adapter->ad_proxy) {
933 bt_shell_printf("Advertising Features:\n");
934 print_property(adapter->ad_proxy, "ActiveInstances");
935 print_property(adapter->ad_proxy, "SupportedInstances");
936 print_property(adapter->ad_proxy, "SupportedIncludes");
937 print_property(adapter->ad_proxy, "SupportedSecondaryChannels");
940 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
943 static void cmd_select(int argc, char *argv[])
945 struct adapter *adapter;
947 adapter = find_ctrl_by_address(ctrl_list, argv[1]);
949 bt_shell_printf("Controller %s not available\n", argv[1]);
950 return bt_shell_noninteractive_quit(EXIT_FAILURE);
953 if (default_ctrl && default_ctrl->proxy == adapter->proxy)
954 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
956 default_ctrl = adapter;
957 print_adapter(adapter->proxy, NULL);
959 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
962 static void cmd_devices(int argc, char *argv[])
966 if (check_default_ctrl() == FALSE)
967 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
969 for (ll = g_list_first(default_ctrl->devices);
970 ll; ll = g_list_next(ll)) {
971 GDBusProxy *proxy = ll->data;
972 print_device(proxy, NULL);
975 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
978 static void cmd_paired_devices(int argc, char *argv[])
982 if (check_default_ctrl() == FALSE)
983 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
985 for (ll = g_list_first(default_ctrl->devices);
986 ll; ll = g_list_next(ll)) {
987 GDBusProxy *proxy = ll->data;
988 DBusMessageIter iter;
991 if (g_dbus_proxy_get_property(proxy, "Paired", &iter) == FALSE)
994 dbus_message_iter_get_basic(&iter, &paired);
998 print_device(proxy, NULL);
1001 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1004 static void generic_callback(const DBusError *error, void *user_data)
1006 char *str = user_data;
1008 if (dbus_error_is_set(error)) {
1009 bt_shell_printf("Failed to set %s: %s\n", str, error->name);
1010 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1012 bt_shell_printf("Changing %s succeeded\n", str);
1013 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1017 static void cmd_system_alias(int argc, char *argv[])
1021 if (check_default_ctrl() == FALSE)
1022 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1024 name = g_strdup(argv[1]);
1026 if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Alias",
1027 DBUS_TYPE_STRING, &name,
1028 generic_callback, name, g_free) == TRUE)
1034 static void cmd_reset_alias(int argc, char *argv[])
1038 if (check_default_ctrl() == FALSE)
1039 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1041 name = g_strdup("");
1043 if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Alias",
1044 DBUS_TYPE_STRING, &name,
1045 generic_callback, name, g_free) == TRUE)
1051 static void cmd_power(int argc, char *argv[])
1053 dbus_bool_t powered;
1056 if (!parse_argument(argc, argv, NULL, NULL, &powered, NULL))
1057 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1059 if (check_default_ctrl() == FALSE)
1060 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1062 str = g_strdup_printf("power %s", powered == TRUE ? "on" : "off");
1064 if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Powered",
1065 DBUS_TYPE_BOOLEAN, &powered,
1066 generic_callback, str, g_free) == TRUE)
1072 static void cmd_pairable(int argc, char *argv[])
1074 dbus_bool_t pairable;
1077 if (!parse_argument(argc, argv, NULL, NULL, &pairable, NULL))
1078 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1080 if (check_default_ctrl() == FALSE)
1081 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1083 str = g_strdup_printf("pairable %s", pairable == TRUE ? "on" : "off");
1085 if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Pairable",
1086 DBUS_TYPE_BOOLEAN, &pairable,
1087 generic_callback, str, g_free) == TRUE)
1092 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1095 static void cmd_discoverable(int argc, char *argv[])
1097 dbus_bool_t discoverable;
1100 if (!parse_argument(argc, argv, NULL, NULL, &discoverable, NULL))
1101 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1103 if (check_default_ctrl() == FALSE)
1104 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1106 str = g_strdup_printf("discoverable %s",
1107 discoverable == TRUE ? "on" : "off");
1109 if (g_dbus_proxy_set_property_basic(default_ctrl->proxy, "Discoverable",
1110 DBUS_TYPE_BOOLEAN, &discoverable,
1111 generic_callback, str, g_free) == TRUE)
1116 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1119 static void cmd_discoverable_timeout(int argc, char *argv[])
1122 char *endptr = NULL;
1126 DBusMessageIter iter;
1128 if (!g_dbus_proxy_get_property(default_ctrl->proxy,
1129 "DiscoverableTimeout", &iter)) {
1130 bt_shell_printf("Unable to get DiscoverableTimeout\n");
1131 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1134 dbus_message_iter_get_basic(&iter, &value);
1136 bt_shell_printf("DiscoverableTimeout: %d seconds\n", value);
1141 value = strtol(argv[1], &endptr, 0);
1142 if (!endptr || *endptr != '\0' || value > UINT32_MAX) {
1143 bt_shell_printf("Invalid argument\n");
1144 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1147 str = g_strdup_printf("discoverable-timeout %d", value);
1149 if (g_dbus_proxy_set_property_basic(default_ctrl->proxy,
1150 "DiscoverableTimeout",
1151 DBUS_TYPE_UINT32, &value,
1152 generic_callback, str, g_free))
1157 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1160 static void cmd_agent(int argc, char *argv[])
1163 const char *capability;
1165 if (!parse_argument(argc, argv, agent_arguments, "capability",
1166 &enable, &capability))
1167 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1169 if (enable == TRUE) {
1170 g_free(auto_register_agent);
1171 auto_register_agent = g_strdup(capability);
1174 agent_register(dbus_conn, agent_manager,
1175 auto_register_agent);
1177 bt_shell_printf("Agent registration enabled\n");
1179 g_free(auto_register_agent);
1180 auto_register_agent = NULL;
1183 agent_unregister(dbus_conn, agent_manager);
1185 bt_shell_printf("Agent registration disabled\n");
1188 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1191 static void cmd_default_agent(int argc, char *argv[])
1193 agent_default(dbus_conn, agent_manager);
1196 #define DISTANCE_VAL_INVALID 0x7FFF
1198 static struct set_discovery_filter_args {
1202 dbus_int16_t pathloss;
1205 dbus_bool_t duplicate;
1206 dbus_bool_t discoverable;
1210 .rssi = DISTANCE_VAL_INVALID,
1211 .pathloss = DISTANCE_VAL_INVALID,
1215 static void start_discovery_reply(DBusMessage *message, void *user_data)
1217 dbus_bool_t enable = GPOINTER_TO_UINT(user_data);
1220 dbus_error_init(&error);
1222 if (dbus_set_error_from_message(&error, message) == TRUE) {
1223 bt_shell_printf("Failed to %s discovery: %s\n",
1224 enable == TRUE ? "start" : "stop", error.name);
1225 dbus_error_free(&error);
1226 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1229 bt_shell_printf("Discovery %s\n", enable ? "started" : "stopped");
1231 filter.active = enable;
1232 /* Leave the discovery running even on noninteractive mode */
1235 static void clear_discovery_filter(DBusMessageIter *iter, void *user_data)
1237 DBusMessageIter dict;
1239 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1240 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1241 DBUS_TYPE_STRING_AS_STRING
1242 DBUS_TYPE_VARIANT_AS_STRING
1243 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
1245 dbus_message_iter_close_container(iter, &dict);
1248 static void set_discovery_filter_setup(DBusMessageIter *iter, void *user_data)
1250 struct set_discovery_filter_args *args = user_data;
1251 DBusMessageIter dict;
1253 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1254 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1255 DBUS_TYPE_STRING_AS_STRING
1256 DBUS_TYPE_VARIANT_AS_STRING
1257 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
1259 g_dbus_dict_append_array(&dict, "UUIDs", DBUS_TYPE_STRING,
1263 if (args->pathloss != DISTANCE_VAL_INVALID)
1264 g_dbus_dict_append_entry(&dict, "Pathloss", DBUS_TYPE_UINT16,
1267 if (args->rssi != DISTANCE_VAL_INVALID)
1268 g_dbus_dict_append_entry(&dict, "RSSI", DBUS_TYPE_INT16,
1271 if (args->transport != NULL)
1272 g_dbus_dict_append_entry(&dict, "Transport", DBUS_TYPE_STRING,
1275 if (args->duplicate)
1276 g_dbus_dict_append_entry(&dict, "DuplicateData",
1280 if (args->discoverable)
1281 g_dbus_dict_append_entry(&dict, "Discoverable",
1283 &args->discoverable);
1285 if (args->pattern != NULL)
1286 g_dbus_dict_append_entry(&dict, "Pattern", DBUS_TYPE_STRING,
1289 dbus_message_iter_close_container(iter, &dict);
1293 static void set_discovery_filter_reply(DBusMessage *message, void *user_data)
1297 dbus_error_init(&error);
1298 if (dbus_set_error_from_message(&error, message) == TRUE) {
1299 bt_shell_printf("SetDiscoveryFilter failed: %s\n", error.name);
1300 dbus_error_free(&error);
1301 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1306 bt_shell_printf("SetDiscoveryFilter success\n");
1308 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1311 static void set_discovery_filter(bool cleared)
1313 GDBusSetupFunction func;
1315 if (check_default_ctrl() == FALSE || filter.set)
1318 func = cleared ? clear_discovery_filter : set_discovery_filter_setup;
1320 if (g_dbus_proxy_method_call(default_ctrl->proxy, "SetDiscoveryFilter",
1321 func, set_discovery_filter_reply,
1322 &filter, NULL) == FALSE) {
1323 bt_shell_printf("Failed to set discovery filter\n");
1324 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1330 static void cmd_scan(int argc, char *argv[])
1335 if (!parse_argument(argc, argv, NULL, NULL, &enable, NULL))
1336 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1338 if (check_default_ctrl() == FALSE)
1339 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1341 if (enable == TRUE) {
1342 set_discovery_filter(false);
1343 method = "StartDiscovery";
1345 method = "StopDiscovery";
1347 if (g_dbus_proxy_method_call(default_ctrl->proxy, method,
1348 NULL, start_discovery_reply,
1349 GUINT_TO_POINTER(enable), NULL) == FALSE) {
1350 bt_shell_printf("Failed to %s discovery\n",
1351 enable == TRUE ? "start" : "stop");
1352 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1356 static void cmd_scan_filter_uuids(int argc, char *argv[])
1358 if (argc < 2 || !strlen(argv[1])) {
1361 for (uuid = filter.uuids; uuid && *uuid; uuid++)
1364 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1367 g_strfreev(filter.uuids);
1368 filter.uuids = NULL;
1369 filter.uuids_len = 0;
1371 if (!strcmp(argv[1], "all"))
1374 filter.uuids = g_strdupv(&argv[1]);
1375 if (!filter.uuids) {
1376 bt_shell_printf("Failed to parse input\n");
1377 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1380 filter.uuids_len = g_strv_length(filter.uuids);
1386 set_discovery_filter(false);
1389 static void cmd_scan_filter_rssi(int argc, char *argv[])
1391 if (argc < 2 || !strlen(argv[1])) {
1392 if (filter.rssi != DISTANCE_VAL_INVALID)
1393 bt_shell_printf("RSSI: %d\n", filter.rssi);
1394 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1397 filter.pathloss = DISTANCE_VAL_INVALID;
1398 filter.rssi = atoi(argv[1]);
1403 set_discovery_filter(false);
1406 static void cmd_scan_filter_pathloss(int argc, char *argv[])
1408 if (argc < 2 || !strlen(argv[1])) {
1409 if (filter.pathloss != DISTANCE_VAL_INVALID)
1410 bt_shell_printf("Pathloss: %d\n",
1412 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1415 filter.rssi = DISTANCE_VAL_INVALID;
1416 filter.pathloss = atoi(argv[1]);
1421 set_discovery_filter(false);
1424 static void cmd_scan_filter_transport(int argc, char *argv[])
1426 if (argc < 2 || !strlen(argv[1])) {
1427 if (filter.transport)
1428 bt_shell_printf("Transport: %s\n",
1430 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1433 g_free(filter.transport);
1434 filter.transport = g_strdup(argv[1]);
1439 set_discovery_filter(false);
1442 static void cmd_scan_filter_duplicate_data(int argc, char *argv[])
1444 if (argc < 2 || !strlen(argv[1])) {
1445 bt_shell_printf("DuplicateData: %s\n",
1446 filter.duplicate ? "on" : "off");
1447 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1450 if (!strcmp(argv[1], "on"))
1451 filter.duplicate = true;
1452 else if (!strcmp(argv[1], "off"))
1453 filter.duplicate = false;
1455 bt_shell_printf("Invalid option: %s\n", argv[1]);
1456 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1462 set_discovery_filter(false);
1465 static void cmd_scan_filter_discoverable(int argc, char *argv[])
1467 if (argc < 2 || !strlen(argv[1])) {
1468 bt_shell_printf("Discoverable: %s\n",
1469 filter.discoverable ? "on" : "off");
1470 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1473 if (!strcmp(argv[1], "on"))
1474 filter.discoverable = true;
1475 else if (!strcmp(argv[1], "off"))
1476 filter.discoverable = false;
1478 bt_shell_printf("Invalid option: %s\n", argv[1]);
1479 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1485 set_discovery_filter(false);
1488 static void cmd_scan_filter_pattern(int argc, char *argv[])
1490 if (argc < 2 || !strlen(argv[1])) {
1491 bt_shell_printf("Pattern: %s\n", filter.pattern);
1492 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1495 free(filter.pattern);
1496 filter.pattern = strdup(argv[1]);
1501 set_discovery_filter(false);
1504 static void filter_clear_uuids(void)
1506 g_strfreev(filter.uuids);
1507 filter.uuids = NULL;
1508 filter.uuids_len = 0;
1511 static void filter_clear_rssi(void)
1513 filter.rssi = DISTANCE_VAL_INVALID;
1516 static void filter_clear_pathloss(void)
1518 filter.pathloss = DISTANCE_VAL_INVALID;
1521 static void filter_clear_transport(void)
1523 g_free(filter.transport);
1524 filter.transport = NULL;
1527 static void filter_clear_duplicate(void)
1529 filter.duplicate = false;
1532 static void filter_clear_discoverable(void)
1534 filter.discoverable = false;
1537 static void filter_clear_pattern(void)
1539 free(filter.pattern);
1540 filter.pattern = NULL;
1543 struct clear_entry {
1545 void (*clear) (void);
1548 static const struct clear_entry filter_clear[] = {
1549 { "uuids", filter_clear_uuids },
1550 { "rssi", filter_clear_rssi },
1551 { "pathloss", filter_clear_pathloss },
1552 { "transport", filter_clear_transport },
1553 { "duplicate-data", filter_clear_duplicate },
1554 { "discoverable", filter_clear_discoverable },
1555 { "pattern", filter_clear_pattern },
1559 static char *filter_clear_generator(const char *text, int state)
1561 static int index, len;
1569 while ((arg = filter_clear[index].name)) {
1572 if (!strncmp(arg, text, len))
1579 static gboolean data_clear(const struct clear_entry *entry_table,
1582 const struct clear_entry *entry;
1585 if (!name || !strlen(name) || !strcmp("all", name))
1588 for (entry = entry_table; entry && entry->name; entry++) {
1589 if (all || !strcmp(entry->name, name)) {
1597 bt_shell_printf("Invalid argument %s\n", name);
1605 static void cmd_scan_filter_clear(int argc, char *argv[])
1609 if (argc < 2 || !strlen(argv[1]))
1612 if (!data_clear(filter_clear, all ? "all" : argv[1]))
1613 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1617 if (check_default_ctrl() == FALSE)
1618 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1620 set_discovery_filter(all);
1623 static struct GDBusProxy *find_device(int argc, char *argv[])
1627 if (argc < 2 || !strlen(argv[1])) {
1630 bt_shell_printf("Missing device address argument\n");
1634 if (check_default_ctrl() == FALSE)
1637 proxy = find_proxy_by_address(default_ctrl->devices, argv[1]);
1639 bt_shell_printf("Device %s not available\n", argv[1]);
1646 static void cmd_info(int argc, char *argv[])
1649 GDBusProxy *battery_proxy;
1650 DBusMessageIter iter;
1651 const char *address;
1653 proxy = find_device(argc, argv);
1655 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1657 if (g_dbus_proxy_get_property(proxy, "Address", &iter) == FALSE)
1658 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1660 dbus_message_iter_get_basic(&iter, &address);
1662 if (g_dbus_proxy_get_property(proxy, "AddressType", &iter) == TRUE) {
1665 dbus_message_iter_get_basic(&iter, &type);
1667 bt_shell_printf("Device %s (%s)\n", address, type);
1669 bt_shell_printf("Device %s\n", address);
1672 print_property(proxy, "Name");
1673 print_property(proxy, "Alias");
1674 print_property(proxy, "Class");
1675 print_property(proxy, "Appearance");
1676 print_property(proxy, "Icon");
1677 print_property(proxy, "Paired");
1678 print_property(proxy, "Trusted");
1679 print_property(proxy, "Blocked");
1680 print_property(proxy, "Connected");
1681 print_property(proxy, "WakeAllowed");
1682 print_property(proxy, "LegacyPairing");
1684 print_property(proxy, "Modalias");
1685 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1686 print_property(proxy, "LegacyManufacturerDataLen");
1688 print_property(proxy, "ManufacturerData");
1689 print_property(proxy, "ServiceData");
1690 print_property(proxy, "RSSI");
1691 print_property(proxy, "TxPower");
1692 print_property(proxy, "AdvertisingFlags");
1693 print_property(proxy, "AdvertisingData");
1695 battery_proxy = find_battery_by_path(battery_proxies,
1696 g_dbus_proxy_get_path(proxy));
1697 print_property_with_label(battery_proxy, "Percentage",
1698 "Battery Percentage");
1700 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1703 static void pair_reply(DBusMessage *message, void *user_data)
1707 dbus_error_init(&error);
1709 if (dbus_set_error_from_message(&error, message) == TRUE) {
1710 bt_shell_printf("Failed to pair: %s\n", error.name);
1711 dbus_error_free(&error);
1712 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1715 bt_shell_printf("Pairing successful\n");
1717 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1720 static const char *proxy_address(GDBusProxy *proxy)
1722 DBusMessageIter iter;
1725 if (!g_dbus_proxy_get_property(proxy, "Address", &iter))
1728 dbus_message_iter_get_basic(&iter, &addr);
1733 static void cmd_pair(int argc, char *argv[])
1737 proxy = find_device(argc, argv);
1739 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1741 if (g_dbus_proxy_method_call(proxy, "Pair", NULL, pair_reply,
1742 NULL, NULL) == FALSE) {
1743 bt_shell_printf("Failed to pair\n");
1744 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1747 bt_shell_printf("Attempting to pair with %s\n", proxy_address(proxy));
1750 static void cmd_trust(int argc, char *argv[])
1753 dbus_bool_t trusted;
1756 proxy = find_device(argc, argv);
1758 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1762 str = g_strdup_printf("%s trust", proxy_address(proxy));
1764 if (g_dbus_proxy_set_property_basic(proxy, "Trusted",
1765 DBUS_TYPE_BOOLEAN, &trusted,
1766 generic_callback, str, g_free) == TRUE)
1771 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1774 static void cmd_untrust(int argc, char *argv[])
1777 dbus_bool_t trusted;
1780 proxy = find_device(argc, argv);
1782 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1786 str = g_strdup_printf("%s untrust", proxy_address(proxy));
1788 if (g_dbus_proxy_set_property_basic(proxy, "Trusted",
1789 DBUS_TYPE_BOOLEAN, &trusted,
1790 generic_callback, str, g_free) == TRUE)
1795 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1798 static void cmd_block(int argc, char *argv[])
1801 dbus_bool_t blocked;
1804 proxy = find_device(argc, argv);
1806 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1810 str = g_strdup_printf("%s block", proxy_address(proxy));
1812 if (g_dbus_proxy_set_property_basic(proxy, "Blocked",
1813 DBUS_TYPE_BOOLEAN, &blocked,
1814 generic_callback, str, g_free) == TRUE)
1819 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1822 static void cmd_unblock(int argc, char *argv[])
1825 dbus_bool_t blocked;
1828 proxy = find_device(argc, argv);
1830 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1834 str = g_strdup_printf("%s unblock", proxy_address(proxy));
1836 if (g_dbus_proxy_set_property_basic(proxy, "Blocked",
1837 DBUS_TYPE_BOOLEAN, &blocked,
1838 generic_callback, str, g_free) == TRUE)
1843 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1846 static void remove_device_reply(DBusMessage *message, void *user_data)
1850 dbus_error_init(&error);
1852 if (dbus_set_error_from_message(&error, message) == TRUE) {
1853 bt_shell_printf("Failed to remove device: %s\n", error.name);
1854 dbus_error_free(&error);
1855 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1858 bt_shell_printf("Device has been removed\n");
1859 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1862 static void remove_device_setup(DBusMessageIter *iter, void *user_data)
1864 const char *path = user_data;
1866 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
1869 static void remove_device(GDBusProxy *proxy)
1876 path = g_strdup(g_dbus_proxy_get_path(proxy));
1878 if (g_dbus_proxy_method_call(default_ctrl->proxy, "RemoveDevice",
1879 remove_device_setup,
1880 remove_device_reply,
1881 path, g_free) == FALSE) {
1882 bt_shell_printf("Failed to remove device\n");
1884 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1888 static void cmd_remove(int argc, char *argv[])
1892 if (check_default_ctrl() == FALSE)
1893 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1895 if (strcmp(argv[1], "*") == 0) {
1898 for (list = default_ctrl->devices; list;
1899 list = g_list_next(list)) {
1900 GDBusProxy *proxy = list->data;
1902 remove_device(proxy);
1907 proxy = find_proxy_by_address(default_ctrl->devices, argv[1]);
1909 bt_shell_printf("Device %s not available\n", argv[1]);
1910 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1913 remove_device(proxy);
1916 static void connect_reply(DBusMessage *message, void *user_data)
1918 GDBusProxy *proxy = user_data;
1921 dbus_error_init(&error);
1923 if (dbus_set_error_from_message(&error, message) == TRUE) {
1924 bt_shell_printf("Failed to connect: %s\n", error.name);
1925 dbus_error_free(&error);
1926 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1929 bt_shell_printf("Connection successful\n");
1931 set_default_device(proxy, NULL);
1932 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1935 static void cmd_connect(int argc, char *argv[])
1939 if (check_default_ctrl() == FALSE)
1940 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1942 proxy = find_proxy_by_address(default_ctrl->devices, argv[1]);
1944 bt_shell_printf("Device %s not available\n", argv[1]);
1945 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1948 if (g_dbus_proxy_method_call(proxy, "Connect", NULL, connect_reply,
1949 proxy, NULL) == FALSE) {
1950 bt_shell_printf("Failed to connect\n");
1951 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1954 bt_shell_printf("Attempting to connect to %s\n", argv[1]);
1957 static void disconn_reply(DBusMessage *message, void *user_data)
1959 GDBusProxy *proxy = user_data;
1962 dbus_error_init(&error);
1964 if (dbus_set_error_from_message(&error, message) == TRUE) {
1965 bt_shell_printf("Failed to disconnect: %s\n", error.name);
1966 dbus_error_free(&error);
1967 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1970 bt_shell_printf("Successful disconnected\n");
1972 if (proxy == default_dev)
1973 set_default_device(NULL, NULL);
1975 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
1978 static void cmd_disconn(int argc, char *argv[])
1982 proxy = find_device(argc, argv);
1984 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1986 if (g_dbus_proxy_method_call(proxy, "Disconnect", NULL, disconn_reply,
1987 proxy, NULL) == FALSE) {
1988 bt_shell_printf("Failed to disconnect\n");
1989 return bt_shell_noninteractive_quit(EXIT_FAILURE);
1992 bt_shell_printf("Attempting to disconnect from %s\n",
1993 proxy_address(proxy));
1996 static void cmd_list_attributes(int argc, char *argv[])
2001 if (argc > 1 && !strcmp(argv[1], "local")) {
2006 proxy = find_device(argc, argv);
2008 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2010 path = g_dbus_proxy_get_path(proxy);
2013 gatt_list_attributes(path);
2015 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
2018 static void cmd_set_alias(int argc, char *argv[])
2023 bt_shell_printf("No device connected\n");
2024 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2027 name = g_strdup(argv[1]);
2029 if (g_dbus_proxy_set_property_basic(default_dev, "Alias",
2030 DBUS_TYPE_STRING, &name,
2031 generic_callback, name, g_free) == TRUE)
2036 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2039 static void cmd_select_attribute(int argc, char *argv[])
2044 bt_shell_printf("No device connected\n");
2045 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2048 proxy = gatt_select_attribute(default_attr, argv[1]);
2050 set_default_attribute(proxy);
2051 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
2054 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2057 static struct GDBusProxy *find_attribute(int argc, char *argv[])
2061 if (argc < 2 || !strlen(argv[1])) {
2063 return default_attr;
2064 bt_shell_printf("Missing attribute argument\n");
2068 proxy = gatt_select_attribute(default_attr, argv[1]);
2070 bt_shell_printf("Attribute %s not available\n", argv[1]);
2077 static void cmd_attribute_info(int argc, char *argv[])
2080 DBusMessageIter iter;
2081 const char *iface, *uuid, *text;
2083 proxy = find_attribute(argc, argv);
2085 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2087 if (g_dbus_proxy_get_property(proxy, "UUID", &iter) == FALSE)
2088 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2090 dbus_message_iter_get_basic(&iter, &uuid);
2092 text = bt_uuidstr_to_str(uuid);
2094 text = g_dbus_proxy_get_path(proxy);
2096 iface = g_dbus_proxy_get_interface(proxy);
2097 if (!strcmp(iface, "org.bluez.GattService1")) {
2098 bt_shell_printf("Service - %s\n", text);
2100 print_property(proxy, "UUID");
2101 print_property(proxy, "Primary");
2102 print_property(proxy, "Characteristics");
2103 print_property(proxy, "Includes");
2104 } else if (!strcmp(iface, "org.bluez.GattCharacteristic1")) {
2105 bt_shell_printf("Characteristic - %s\n", text);
2107 print_property(proxy, "UUID");
2108 print_property(proxy, "Service");
2109 print_property(proxy, "Value");
2110 print_property(proxy, "Notifying");
2111 print_property(proxy, "Flags");
2112 print_property(proxy, "Descriptors");
2113 } else if (!strcmp(iface, "org.bluez.GattDescriptor1")) {
2114 bt_shell_printf("Descriptor - %s\n", text);
2116 print_property(proxy, "UUID");
2117 print_property(proxy, "Characteristic");
2118 print_property(proxy, "Value");
2121 return bt_shell_noninteractive_quit(EXIT_SUCCESS);
2124 static void cmd_read(int argc, char *argv[])
2126 if (!default_attr) {
2127 bt_shell_printf("No attribute selected\n");
2128 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2131 gatt_read_attribute(default_attr, argc, argv);
2134 static void cmd_write(int argc, char *argv[])
2136 if (!default_attr) {
2137 bt_shell_printf("No attribute selected\n");
2138 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2141 gatt_write_attribute(default_attr, argc, argv);
2144 static void cmd_acquire_write(int argc, char *argv[])
2146 if (!default_attr) {
2147 bt_shell_printf("No attribute selected\n");
2148 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2151 gatt_acquire_write(default_attr, argv[1]);
2154 static void cmd_release_write(int argc, char *argv[])
2156 if (!default_attr) {
2157 bt_shell_printf("No attribute selected\n");
2158 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2161 gatt_release_write(default_attr, argv[1]);
2164 static void cmd_acquire_notify(int argc, char *argv[])
2166 if (!default_attr) {
2167 bt_shell_printf("No attribute selected\n");
2168 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2171 gatt_acquire_notify(default_attr, argv[1]);
2174 static void cmd_release_notify(int argc, char *argv[])
2176 if (!default_attr) {
2177 bt_shell_printf("No attribute selected\n");
2178 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2181 gatt_release_notify(default_attr, argv[1]);
2184 static void cmd_notify(int argc, char *argv[])
2188 if (!parse_argument(argc, argv, NULL, NULL, &enable, NULL))
2189 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2191 if (!default_attr) {
2192 bt_shell_printf("No attribute selected\n");
2193 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2196 gatt_notify_attribute(default_attr, enable ? true : false);
2199 static void cmd_clone(int argc, char *argv[])
2203 proxy = default_attr ? default_attr : default_dev;
2205 bt_shell_printf("Not connected\n");
2206 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2209 gatt_clone_attribute(proxy, argc, argv);
2212 static void cmd_register_app(int argc, char *argv[])
2214 if (check_default_ctrl() == FALSE)
2215 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2217 gatt_register_app(dbus_conn, default_ctrl->proxy, argc, argv);
2220 static void cmd_unregister_app(int argc, char *argv[])
2222 if (check_default_ctrl() == FALSE)
2223 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2225 gatt_unregister_app(dbus_conn, default_ctrl->proxy);
2228 static void cmd_register_service(int argc, char *argv[])
2230 if (check_default_ctrl() == FALSE)
2231 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2233 gatt_register_service(dbus_conn, default_ctrl->proxy, argc, argv);
2236 static void cmd_register_includes(int argc, char *argv[])
2238 if (check_default_ctrl() == FALSE)
2239 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2241 gatt_register_include(dbus_conn, default_ctrl->proxy, argc, argv);
2244 static void cmd_unregister_includes(int argc, char *argv[])
2246 if (check_default_ctrl() == FALSE)
2247 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2249 gatt_unregister_include(dbus_conn, default_ctrl->proxy, argc, argv);
2252 static void cmd_unregister_service(int argc, char *argv[])
2254 if (check_default_ctrl() == FALSE)
2255 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2257 gatt_unregister_service(dbus_conn, default_ctrl->proxy, argc, argv);
2260 static void cmd_register_characteristic(int argc, char *argv[])
2262 if (check_default_ctrl() == FALSE)
2263 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2265 gatt_register_chrc(dbus_conn, default_ctrl->proxy, argc, argv);
2268 static void cmd_unregister_characteristic(int argc, char *argv[])
2270 if (check_default_ctrl() == FALSE)
2271 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2273 gatt_unregister_chrc(dbus_conn, default_ctrl->proxy, argc, argv);
2276 static void cmd_register_descriptor(int argc, char *argv[])
2278 if (check_default_ctrl() == FALSE)
2279 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2281 gatt_register_desc(dbus_conn, default_ctrl->proxy, argc, argv);
2284 static void cmd_unregister_descriptor(int argc, char *argv[])
2286 if (check_default_ctrl() == FALSE)
2287 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2289 gatt_unregister_desc(dbus_conn, default_ctrl->proxy, argc, argv);
2292 static char *generic_generator(const char *text, int state,
2293 GList *source, const char *property)
2295 static int index, len;
2303 for (list = g_list_nth(source, index); list;
2304 list = g_list_next(list)) {
2305 GDBusProxy *proxy = list->data;
2306 DBusMessageIter iter;
2311 if (g_dbus_proxy_get_property(proxy, property, &iter) == FALSE)
2314 dbus_message_iter_get_basic(&iter, &str);
2316 if (!strncasecmp(str, text, len))
2323 static char *ctrl_generator(const char *text, int state)
2325 static int index = 0;
2334 for (list = g_list_nth(ctrl_list, index); list;
2335 list = g_list_next(list)) {
2336 struct adapter *adapter = list->data;
2337 DBusMessageIter iter;
2342 if (g_dbus_proxy_get_property(adapter->proxy,
2343 "Address", &iter) == FALSE)
2346 dbus_message_iter_get_basic(&iter, &str);
2348 if (!strncasecmp(str, text, len))
2355 static char *dev_generator(const char *text, int state)
2357 return generic_generator(text, state,
2358 default_ctrl ? default_ctrl->devices : NULL, "Address");
2361 static char *attribute_generator(const char *text, int state)
2363 return gatt_attribute_generator(text, state);
2366 static char *argument_generator(const char *text, int state,
2367 const char *args_list[])
2369 static int index, len;
2377 while ((arg = args_list[index])) {
2380 if (!strncmp(arg, text, len))
2387 static char *capability_generator(const char *text, int state)
2389 return argument_generator(text, state, agent_arguments);
2392 static void cmd_advertise(int argc, char *argv[])
2397 if (!parse_argument(argc, argv, ad_arguments, "type",
2399 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2401 if (!default_ctrl || !default_ctrl->ad_proxy) {
2402 bt_shell_printf("LEAdvertisingManager not found\n");
2403 bt_shell_noninteractive_quit(EXIT_FAILURE);
2407 ad_register(dbus_conn, default_ctrl->ad_proxy, type);
2409 ad_unregister(dbus_conn, default_ctrl->ad_proxy);
2412 static char *ad_generator(const char *text, int state)
2414 return argument_generator(text, state, ad_arguments);
2417 static void cmd_advertise_uuids(int argc, char *argv[])
2419 ad_advertise_uuids(dbus_conn, argc, argv);
2422 static void cmd_advertise_service(int argc, char *argv[])
2424 ad_advertise_service(dbus_conn, argc, argv);
2427 static void cmd_advertise_manufacturer(int argc, char *argv[])
2429 ad_advertise_manufacturer(dbus_conn, argc, argv);
2432 static void cmd_advertise_data(int argc, char *argv[])
2434 ad_advertise_data(dbus_conn, argc, argv);
2437 static void cmd_advertise_discoverable(int argc, char *argv[])
2439 dbus_bool_t discoverable;
2442 ad_advertise_discoverable(dbus_conn, NULL);
2446 if (!parse_argument(argc, argv, NULL, NULL, &discoverable, NULL))
2447 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2449 ad_advertise_discoverable(dbus_conn, &discoverable);
2452 static void cmd_advertise_discoverable_timeout(int argc, char *argv[])
2455 char *endptr = NULL;
2458 ad_advertise_discoverable_timeout(dbus_conn, NULL);
2462 value = strtol(argv[1], &endptr, 0);
2463 if (!endptr || *endptr != '\0' || value > UINT16_MAX) {
2464 bt_shell_printf("Invalid argument\n");
2465 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2468 ad_advertise_discoverable_timeout(dbus_conn, &value);
2471 static void cmd_advertise_tx_power(int argc, char *argv[])
2473 dbus_bool_t powered;
2476 ad_advertise_tx_power(dbus_conn, NULL);
2480 if (!parse_argument(argc, argv, NULL, NULL, &powered, NULL))
2481 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2483 ad_advertise_tx_power(dbus_conn, &powered);
2486 static void cmd_advertise_name(int argc, char *argv[])
2489 ad_advertise_local_name(dbus_conn, NULL);
2493 if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "yes") == 0) {
2494 ad_advertise_name(dbus_conn, true);
2498 if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "no") == 0) {
2499 ad_advertise_name(dbus_conn, false);
2503 ad_advertise_local_name(dbus_conn, argv[1]);
2506 static void cmd_advertise_appearance(int argc, char *argv[])
2509 char *endptr = NULL;
2512 ad_advertise_local_appearance(dbus_conn, NULL);
2516 if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "yes") == 0) {
2517 ad_advertise_appearance(dbus_conn, true);
2521 if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "no") == 0) {
2522 ad_advertise_appearance(dbus_conn, false);
2526 value = strtol(argv[1], &endptr, 0);
2527 if (!endptr || *endptr != '\0' || value > UINT16_MAX) {
2528 bt_shell_printf("Invalid argument\n");
2529 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2532 ad_advertise_local_appearance(dbus_conn, &value);
2535 static void cmd_advertise_duration(int argc, char *argv[])
2538 char *endptr = NULL;
2541 ad_advertise_duration(dbus_conn, NULL);
2545 value = strtol(argv[1], &endptr, 0);
2546 if (!endptr || *endptr != '\0' || value > UINT16_MAX) {
2547 bt_shell_printf("Invalid argument\n");
2548 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2551 ad_advertise_duration(dbus_conn, &value);
2554 static void cmd_advertise_timeout(int argc, char *argv[])
2557 char *endptr = NULL;
2560 ad_advertise_timeout(dbus_conn, NULL);
2564 value = strtol(argv[1], &endptr, 0);
2565 if (!endptr || *endptr != '\0' || value > UINT16_MAX) {
2566 bt_shell_printf("Invalid argument\n");
2567 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2570 ad_advertise_timeout(dbus_conn, &value);
2573 static void cmd_advertise_secondary(int argc, char *argv[])
2576 ad_advertise_secondary(dbus_conn, NULL);
2580 ad_advertise_secondary(dbus_conn, argv[1]);
2583 static void ad_clear_uuids(void)
2585 ad_disable_uuids(dbus_conn);
2588 static void ad_clear_service(void)
2590 ad_disable_service(dbus_conn);
2593 static void ad_clear_manufacturer(void)
2595 ad_disable_manufacturer(dbus_conn);
2598 static void ad_clear_data(void)
2600 ad_disable_data(dbus_conn);
2603 static void ad_clear_tx_power(void)
2605 dbus_bool_t powered = false;
2607 ad_advertise_tx_power(dbus_conn, &powered);
2610 static void ad_clear_name(void)
2612 ad_advertise_name(dbus_conn, false);
2615 static void ad_clear_appearance(void)
2617 ad_advertise_appearance(dbus_conn, false);
2620 static void ad_clear_duration(void)
2624 ad_advertise_duration(dbus_conn, &value);
2627 static void ad_clear_timeout(void)
2631 ad_advertise_timeout(dbus_conn, &value);
2634 static void ad_clear_secondary(void)
2636 const char *value = "";
2638 ad_advertise_secondary(dbus_conn, value);
2641 static const struct clear_entry ad_clear[] = {
2642 { "uuids", ad_clear_uuids },
2643 { "service", ad_clear_service },
2644 { "manufacturer", ad_clear_manufacturer },
2645 { "data", ad_clear_data },
2646 { "tx-power", ad_clear_tx_power },
2647 { "name", ad_clear_name },
2648 { "appearance", ad_clear_appearance },
2649 { "duration", ad_clear_duration },
2650 { "timeout", ad_clear_timeout },
2651 { "secondary", ad_clear_secondary },
2655 static void cmd_ad_clear(int argc, char *argv[])
2659 if (argc < 2 || !strlen(argv[1]))
2662 if(!data_clear(ad_clear, all ? "all" : argv[1]))
2663 return bt_shell_noninteractive_quit(EXIT_FAILURE);
2666 static const struct bt_shell_menu advertise_menu = {
2667 .name = "advertise",
2668 .desc = "Advertise Options Submenu",
2670 { "uuids", "[uuid1 uuid2 ...]", cmd_advertise_uuids,
2671 "Set/Get advertise uuids" },
2672 { "service", "[uuid] [data=xx xx ...]", cmd_advertise_service,
2673 "Set/Get advertise service data" },
2674 { "manufacturer", "[id] [data=xx xx ...]",
2675 cmd_advertise_manufacturer,
2676 "Set/Get advertise manufacturer data" },
2677 { "data", "[type] [data=xx xx ...]", cmd_advertise_data,
2678 "Set/Get advertise data" },
2679 { "discoverable", "[on/off]", cmd_advertise_discoverable,
2680 "Set/Get advertise discoverable" },
2681 { "discoverable-timeout", "[seconds]",
2682 cmd_advertise_discoverable_timeout,
2683 "Set/Get advertise discoverable timeout" },
2684 { "tx-power", "[on/off]", cmd_advertise_tx_power,
2685 "Show/Enable/Disable TX power to be advertised",
2687 { "name", "[on/off/name]", cmd_advertise_name,
2688 "Configure local name to be advertised" },
2689 { "appearance", "[on/off/value]", cmd_advertise_appearance,
2690 "Configure custom appearance to be advertised" },
2691 { "duration", "[seconds]", cmd_advertise_duration,
2692 "Set/Get advertise duration" },
2693 { "timeout", "[seconds]", cmd_advertise_timeout,
2694 "Set/Get advertise timeout" },
2695 { "secondary", "[1M/2M/Coded]", cmd_advertise_secondary,
2696 "Set/Get advertise secondary channel" },
2697 { "clear", "[uuids/service/manufacturer/config-name...]", cmd_ad_clear,
2698 "Clear advertise config" },
2702 static const struct bt_shell_menu scan_menu = {
2704 .desc = "Scan Options Submenu",
2706 { "uuids", "[all/uuid1 uuid2 ...]", cmd_scan_filter_uuids,
2707 "Set/Get UUIDs filter" },
2708 { "rssi", "[rssi]", cmd_scan_filter_rssi,
2709 "Set/Get RSSI filter, and clears pathloss" },
2710 { "pathloss", "[pathloss]", cmd_scan_filter_pathloss,
2711 "Set/Get Pathloss filter, and clears RSSI" },
2712 { "transport", "[transport]", cmd_scan_filter_transport,
2713 "Set/Get transport filter" },
2714 { "duplicate-data", "[on/off]", cmd_scan_filter_duplicate_data,
2715 "Set/Get duplicate data filter",
2717 { "discoverable", "[on/off]", cmd_scan_filter_discoverable,
2718 "Set/Get discoverable filter",
2720 { "pattern", "[value]", cmd_scan_filter_pattern,
2721 "Set/Get pattern filter",
2724 "[uuids/rssi/pathloss/transport/duplicate-data/discoverable/pattern]",
2725 cmd_scan_filter_clear,
2726 "Clears discovery filter.",
2727 filter_clear_generator },
2731 static const struct bt_shell_menu gatt_menu = {
2733 .desc = "Generic Attribute Submenu",
2735 { "list-attributes", "[dev/local]", cmd_list_attributes,
2736 "List attributes", dev_generator },
2737 { "select-attribute", "<attribute/UUID>", cmd_select_attribute,
2738 "Select attribute", attribute_generator },
2739 { "attribute-info", "[attribute/UUID]", cmd_attribute_info,
2740 "Select attribute", attribute_generator },
2741 { "read", "[offset]", cmd_read, "Read attribute value" },
2742 { "write", "<data=xx xx ...> [offset] [type]", cmd_write,
2743 "Write attribute value" },
2744 { "acquire-write", NULL, cmd_acquire_write,
2745 "Acquire Write file descriptor" },
2746 { "release-write", NULL, cmd_release_write,
2747 "Release Write file descriptor" },
2748 { "acquire-notify", NULL, cmd_acquire_notify,
2749 "Acquire Notify file descriptor" },
2750 { "release-notify", NULL, cmd_release_notify,
2751 "Release Notify file descriptor" },
2752 { "notify", "<on/off>", cmd_notify, "Notify attribute value",
2754 { "clone", "[dev/attribute/UUID]", cmd_clone,
2755 "Clone a device or attribute" },
2756 { "register-application", "[UUID ...]", cmd_register_app,
2757 "Register profile to connect" },
2758 { "unregister-application", NULL, cmd_unregister_app,
2759 "Unregister profile" },
2760 { "register-service", "<UUID> [handle]", cmd_register_service,
2761 "Register application service." },
2762 { "unregister-service", "<UUID/object>", cmd_unregister_service,
2763 "Unregister application service" },
2764 { "register-includes", "<UUID> [handle]", cmd_register_includes,
2765 "Register as Included service in." },
2766 { "unregister-includes", "<Service-UUID><Inc-UUID>",
2767 cmd_unregister_includes,
2768 "Unregister Included service." },
2769 { "register-characteristic",
2770 "<UUID> <Flags=read,write,notify...> [handle]",
2771 cmd_register_characteristic,
2772 "Register application characteristic" },
2773 { "unregister-characteristic", "<UUID/object>",
2774 cmd_unregister_characteristic,
2775 "Unregister application characteristic" },
2776 { "register-descriptor", "<UUID> <Flags=read,write...> [handle]",
2777 cmd_register_descriptor,
2778 "Register application descriptor" },
2779 { "unregister-descriptor", "<UUID/object>",
2780 cmd_unregister_descriptor,
2781 "Unregister application descriptor" },
2785 static const struct bt_shell_menu main_menu = {
2788 { "list", NULL, cmd_list, "List available controllers" },
2789 { "show", "[ctrl]", cmd_show, "Controller information",
2791 { "select", "<ctrl>", cmd_select, "Select default controller",
2793 { "devices", NULL, cmd_devices, "List available devices" },
2794 { "paired-devices", NULL, cmd_paired_devices,
2795 "List paired devices"},
2796 { "system-alias", "<name>", cmd_system_alias,
2797 "Set controller alias" },
2798 { "reset-alias", NULL, cmd_reset_alias,
2799 "Reset controller alias" },
2800 { "power", "<on/off>", cmd_power, "Set controller power",
2802 { "pairable", "<on/off>", cmd_pairable,
2803 "Set controller pairable mode",
2805 { "discoverable", "<on/off>", cmd_discoverable,
2806 "Set controller discoverable mode",
2808 { "discoverable-timeout", "[value]", cmd_discoverable_timeout,
2809 "Set discoverable timeout", NULL },
2810 { "agent", "<on/off/capability>", cmd_agent,
2811 "Enable/disable agent with given capability",
2812 capability_generator},
2813 { "default-agent",NULL, cmd_default_agent,
2814 "Set agent as the default one" },
2815 { "advertise", "<on/off/type>", cmd_advertise,
2816 "Enable/disable advertising with given type",
2818 { "set-alias", "<alias>", cmd_set_alias, "Set device alias" },
2819 { "scan", "<on/off>", cmd_scan, "Scan for devices", NULL },
2820 { "info", "[dev]", cmd_info, "Device information",
2822 { "pair", "[dev]", cmd_pair, "Pair with device",
2824 { "trust", "[dev]", cmd_trust, "Trust device",
2826 { "untrust", "[dev]", cmd_untrust, "Untrust device",
2828 { "block", "[dev]", cmd_block, "Block device",
2830 { "unblock", "[dev]", cmd_unblock, "Unblock device",
2832 { "remove", "<dev>", cmd_remove, "Remove device",
2834 { "connect", "<dev>", cmd_connect, "Connect device",
2836 { "disconnect", "[dev]", cmd_disconn, "Disconnect device",
2841 static const struct option options[] = {
2842 { "agent", required_argument, 0, 'a' },
2846 static const char *agent_option;
2848 static const char **optargs[] = {
2852 static const char *help[] = {
2853 "Register agent handler: <capability>"
2856 static const struct bt_shell_opt opt = {
2858 .optno = sizeof(options) / sizeof(struct option),
2864 static void client_ready(GDBusClient *client, void *user_data)
2866 setup_standard_input();
2869 int main(int argc, char *argv[])
2871 GDBusClient *client;
2874 bt_shell_init(argc, argv, &opt);
2875 bt_shell_set_menu(&main_menu);
2876 bt_shell_add_submenu(&advertise_menu);
2877 bt_shell_add_submenu(&scan_menu);
2878 bt_shell_add_submenu(&gatt_menu);
2879 bt_shell_set_prompt(PROMPT_OFF);
2882 auto_register_agent = g_strdup(agent_option);
2884 auto_register_agent = g_strdup("");
2886 dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
2887 g_dbus_attach_object_manager(dbus_conn);
2889 bt_shell_set_env("DBUS_CONNECTION", dbus_conn);
2891 client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
2893 g_dbus_client_set_connect_watch(client, connect_handler, NULL);
2894 g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
2895 g_dbus_client_set_signal_watch(client, message_handler, NULL);
2897 g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
2898 property_changed, NULL);
2900 g_dbus_client_set_ready_watch(client, client_ready, NULL);
2902 status = bt_shell_run();
2904 g_dbus_client_unref(client);
2906 dbus_connection_unref(dbus_conn);
2908 g_list_free_full(ctrl_list, proxy_leak);
2910 g_free(auto_register_agent);