• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@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 
get_adapter(DBusConnection * conn)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 
find_device(DBusConnection * conn,const char * adapter,const char * address)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 
remove_device(DBusConnection * conn,const char * adapter,const char * device)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 
set_property(DBusConnection * conn,const char * adapter,const char * key,int type,void * val)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 
usage(void)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 
main(int argc,char * argv[])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