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