Home | History | Annotate | Download | only in test
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2007-2010  Marcel Holtmann <marcel (at) holtmann.org>
      6  *
      7  *
      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.
     12  *
     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.
     17  *
     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
     21  *
     22  */
     23 
     24 #ifdef HAVE_CONFIG_H
     25 #include <config.h>
     26 #endif
     27 
     28 #include <stdio.h>
     29 #include <errno.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <getopt.h>
     33 
     34 #include <dbus/dbus.h>
     35 
     36 #define BLUEZ_SERVICE	"org.bluez"
     37 
     38 #define MANAGER_PATH	"/"
     39 #define MANAGER_INTF	BLUEZ_SERVICE ".Manager"
     40 #define ADAPTER_INTF	BLUEZ_SERVICE ".Adapter"
     41 
     42 static char *get_adapter(DBusConnection *conn)
     43 {
     44 	DBusMessage *message, *reply;
     45 	DBusError error;
     46 	const char *path;
     47 	char *result = NULL;
     48 
     49 	message = dbus_message_new_method_call(BLUEZ_SERVICE, MANAGER_PATH,
     50 					MANAGER_INTF, "DefaultAdapter");
     51 	if (!message)
     52 		return NULL;
     53 
     54 	dbus_error_init(&error);
     55 
     56 	reply = dbus_connection_send_with_reply_and_block(conn,
     57 							message, -1, &error);
     58 
     59 	dbus_message_unref(message);
     60 
     61 	if (!reply) {
     62 		if (dbus_error_is_set(&error) == TRUE) {
     63 			fprintf(stderr, "%s\n", error.message);
     64 			dbus_error_free(&error);
     65 		} else
     66 			fprintf(stderr, "Failed to set property\n");
     67 		return NULL;
     68 	}
     69 
     70 	if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
     71 						DBUS_TYPE_INVALID) == FALSE)
     72 		goto done;
     73 
     74 	printf("Using default adapter %s\n", path);
     75 
     76 	result = strdup(path);
     77 
     78 done:
     79 	dbus_message_unref(reply);
     80 
     81 	return result;
     82 }
     83 
     84 static char *find_device(DBusConnection *conn, const char *adapter,
     85 							const char *address)
     86 {
     87 	DBusMessage *message, *reply;
     88 	DBusError error;
     89 	const char *path;
     90 	char *result = NULL;
     91 
     92 	message = dbus_message_new_method_call(BLUEZ_SERVICE, adapter,
     93 					ADAPTER_INTF, "FindDevice");
     94 	if (!message)
     95 		return NULL;
     96 
     97 	dbus_message_append_args(message, DBUS_TYPE_STRING, &address,
     98 							DBUS_TYPE_INVALID);
     99 
    100 	dbus_error_init(&error);
    101 
    102 	reply = dbus_connection_send_with_reply_and_block(conn,
    103 							message, -1, &error);
    104 
    105 	dbus_message_unref(message);
    106 
    107 	if (!reply) {
    108 		if (dbus_error_is_set(&error) == TRUE) {
    109 			fprintf(stderr, "%s\n", error.message);
    110 			dbus_error_free(&error);
    111 		} else
    112 			fprintf(stderr, "Failed to set property\n");
    113 		return NULL;
    114 	}
    115 
    116 	if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
    117 						DBUS_TYPE_INVALID) == FALSE)
    118 		goto done;
    119 
    120 	printf("Using device %s for address %s\n", path, address);
    121 
    122 	result = strdup(path);
    123 
    124 done:
    125 	dbus_message_unref(reply);
    126 
    127 	return result;
    128 }
    129 
    130 static int remove_device(DBusConnection *conn, const char *adapter,
    131 							const char *device)
    132 {
    133 	DBusMessage *message, *reply;
    134 	DBusError error;
    135 
    136 	message = dbus_message_new_method_call(BLUEZ_SERVICE, adapter,
    137 					ADAPTER_INTF, "RemoveDevice");
    138 	if (!message)
    139 		return -ENOMEM;
    140 
    141 	dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &device,
    142 							DBUS_TYPE_INVALID);
    143 
    144 	dbus_error_init(&error);
    145 
    146 	reply = dbus_connection_send_with_reply_and_block(conn,
    147 							message, -1, &error);
    148 
    149 	dbus_message_unref(message);
    150 
    151 	if (!reply) {
    152 		if (dbus_error_is_set(&error) == TRUE) {
    153 			fprintf(stderr, "%s\n", error.message);
    154 			dbus_error_free(&error);
    155 		} else
    156 			fprintf(stderr, "Failed to set property\n");
    157 		return -EIO;
    158 	}
    159 
    160 	dbus_message_unref(reply);
    161 
    162 	printf("Removed device %s\n", device);
    163 
    164 	return 0;
    165 }
    166 
    167 static int set_property(DBusConnection *conn, const char *adapter,
    168 					const char *key, int type, void *val)
    169 {
    170 	DBusMessage *message, *reply;
    171 	DBusMessageIter array, value;
    172 	DBusError error;
    173 	const char *signature;
    174 
    175 	message = dbus_message_new_method_call(BLUEZ_SERVICE, adapter,
    176 						ADAPTER_INTF, "SetProperty");
    177 	if (!message)
    178 		return -ENOMEM;
    179 
    180 	switch (type) {
    181 	case DBUS_TYPE_BOOLEAN:
    182 		signature = DBUS_TYPE_BOOLEAN_AS_STRING;
    183 		break;
    184 	case DBUS_TYPE_UINT32:
    185 		signature = DBUS_TYPE_UINT32_AS_STRING;
    186 		break;
    187 	default:
    188 		return -EILSEQ;
    189 	}
    190 
    191 	dbus_message_iter_init_append(message, &array);
    192 
    193 	dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &key);
    194 
    195 	dbus_message_iter_open_container(&array, DBUS_TYPE_VARIANT,
    196 							signature, &value);
    197 	dbus_message_iter_append_basic(&value, type, val);
    198 	dbus_message_iter_close_container(&array, &value);
    199 
    200 	dbus_error_init(&error);
    201 
    202 	reply = dbus_connection_send_with_reply_and_block(conn,
    203 							message, -1, &error);
    204 
    205 	dbus_message_unref(message);
    206 
    207 	if (!reply) {
    208 		if (dbus_error_is_set(&error) == TRUE) {
    209 			fprintf(stderr, "%s\n", error.message);
    210 			dbus_error_free(&error);
    211 		} else
    212 			fprintf(stderr, "Failed to set property\n");
    213 		return -EIO;
    214 	}
    215 
    216 	dbus_message_unref(reply);
    217 
    218 	printf("Set property %s for %s\n", key, adapter);
    219 
    220 	return 0;
    221 }
    222 
    223 static void usage(void)
    224 {
    225 	printf("gaptest - GAP testing\n"
    226 		"Usage:\n");
    227 	printf("\tgaptest [options]\n");
    228 	printf("Options:\n"
    229 		"\t-T <timeout>        Set timeout\n"
    230 		"\t-P <powered>        Set powered\n"
    231 		"\t-D <discoverable>   Set discoverable\n"
    232 		"\t-B <pairable>       Set pairable\n"
    233 		"\t-C <address>        Create device\n"
    234 		"\t-R <address>        Remove device\n");
    235 }
    236 
    237 int main(int argc, char *argv[])
    238 {
    239 	DBusConnection *conn;
    240 	char *adapter, *device;
    241 	const char *create = NULL, *remove = NULL;
    242 	int opt, timeout = -1, powered = -1, discoverable = -1, pairable = -1;
    243 
    244 	while ((opt = getopt(argc, argv, "T:P:D:B:C:R:h")) != EOF) {
    245 		switch (opt) {
    246 		case 'T':
    247 			timeout = atoi(optarg);
    248 			break;
    249 		case 'P':
    250 			powered = atoi(optarg);
    251 			break;
    252 		case 'D':
    253 			discoverable = atoi(optarg);
    254 			break;
    255 		case 'B':
    256 			pairable = atoi(optarg);
    257 			break;
    258 		case 'C':
    259 			create = optarg;
    260 			break;
    261 		case 'R':
    262 			remove = optarg;
    263 			break;
    264 		case 'h':
    265 			usage();
    266 			exit(0);
    267 		default:
    268 			usage();
    269 			exit(1);
    270 		}
    271 	}
    272 
    273 	conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
    274 	if (!conn) {
    275 		fprintf(stderr, "Can't get on system bus\n");
    276 		exit(1);
    277 	}
    278 
    279 	adapter = get_adapter(conn);
    280 	if (!adapter) {
    281 		fprintf(stderr, "Can't get default adapter\n");
    282 		exit(1);
    283 	}
    284 
    285 	if (powered >= 0) {
    286 		set_property(conn, adapter, "Powered",
    287 					DBUS_TYPE_BOOLEAN, &powered);
    288 	}
    289 
    290 	if (discoverable >= 0) {
    291 		set_property(conn, adapter, "Discoverable",
    292 					DBUS_TYPE_BOOLEAN, &discoverable);
    293 
    294 		if (timeout >= 0)
    295 			set_property(conn, adapter, "DiscoverableTimeout",
    296 						DBUS_TYPE_UINT32, &timeout);
    297 	}
    298 
    299 	if (pairable >= 0) {
    300 		set_property(conn, adapter, "Pairable",
    301 					DBUS_TYPE_BOOLEAN, &pairable);
    302 
    303 		if (timeout >= 0)
    304 			set_property(conn, adapter, "PairableTimeout",
    305 						DBUS_TYPE_UINT32, &timeout);
    306 	}
    307 
    308 	if (create) {
    309 		device = find_device(conn, adapter, create);
    310 		if (!device) {
    311 			fprintf(stderr, "Can't find device\n");
    312 			exit(1);
    313 		}
    314 
    315 		free(device);
    316 	}
    317 
    318 	if (remove) {
    319 		device = find_device(conn, adapter, remove);
    320 		if (!device) {
    321 			fprintf(stderr, "Can't find device\n");
    322 			exit(1);
    323 		}
    324 
    325 		remove_device(conn, adapter, device);
    326 
    327 		free(device);
    328 	}
    329 
    330 	free(adapter);
    331 
    332 	dbus_connection_unref(conn);
    333 
    334 	return 0;
    335 }
    336