1 /*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2006-2007 Nokia Corporation
6 * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <sys/stat.h>
33 #include <sys/param.h>
34 #include <netinet/in.h>
35
36 #include <bluetooth/bluetooth.h>
37 #include <bluetooth/hci.h>
38 #include <bluetooth/hci_lib.h>
39 #include <bluetooth/sdp.h>
40 #include <bluetooth/sdp_lib.h>
41
42 #include <glib.h>
43 #include <dbus/dbus.h>
44 #include <gdbus.h>
45
46 #include "logging.h"
47 #include "textfile.h"
48
49 #include "error.h"
50 #include "ipc.h"
51 #include "device.h"
52 #include "avdtp.h"
53 #include "control.h"
54 #include "headset.h"
55 #include "sink.h"
56
57 #define CONTROL_CONNECT_TIMEOUT 2000
58
device_get_address(DBusConnection * conn,DBusMessage * msg,void * data)59 static DBusMessage *device_get_address(DBusConnection *conn,
60 DBusMessage *msg, void *data)
61 {
62 struct audio_device *device = data;
63 DBusMessage *reply;
64 char address[18], *ptr = address;
65
66 reply = dbus_message_new_method_return(msg);
67 if (!reply)
68 return NULL;
69
70 ba2str(&device->dst, address);
71
72 dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr,
73 DBUS_TYPE_INVALID);
74
75 return reply;
76 }
77
get_dev_name(DBusConnection * conn,const bdaddr_t * src,const bdaddr_t * bda)78 static char *get_dev_name(DBusConnection *conn, const bdaddr_t *src,
79 const bdaddr_t *bda)
80 {
81 char address[18], filename[PATH_MAX + 1];
82
83 ba2str(src, address);
84
85 /* check if it is in the cache */
86 create_name(filename, PATH_MAX, STORAGEDIR, address, "names");
87
88 ba2str(bda, address);
89 return textfile_caseget(filename, address);
90 }
91
device_get_name(DBusConnection * conn,DBusMessage * msg,void * data)92 static DBusMessage *device_get_name(DBusConnection *conn,
93 DBusMessage *msg, void *data)
94 {
95 struct audio_device *dev = data;
96 DBusMessage *reply;
97 const char *name = dev->name ? dev->name : "";
98
99 reply = dbus_message_new_method_return(msg);
100 if (!reply)
101 return NULL;
102
103 dbus_message_append_args(reply, DBUS_TYPE_STRING, &name,
104 DBUS_TYPE_INVALID);
105
106 return reply;
107 }
108
device_get_adapter(DBusConnection * conn,DBusMessage * msg,void * data)109 static DBusMessage *device_get_adapter(DBusConnection *conn,
110 DBusMessage *msg, void *data)
111 {
112 struct audio_device *device = data;
113 DBusMessage *reply;
114 char address[18], *ptr = address;
115
116 reply = dbus_message_new_method_return(msg);
117 if (!reply)
118 return NULL;
119
120 ba2str(&device->src, address);
121
122 dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr,
123 DBUS_TYPE_INVALID);
124
125 return reply;
126 }
127
128
device_get_connected(DBusConnection * conn,DBusMessage * msg,void * data)129 static DBusMessage *device_get_connected(DBusConnection *conn,
130 DBusMessage *msg, void *data)
131 {
132 DBusMessageIter iter, array_iter;
133 struct audio_device *device = data;
134 DBusMessage *reply;
135 const char *iface;
136
137 reply = dbus_message_new_method_return(msg);
138 if (!reply)
139 return NULL;
140
141 dbus_message_iter_init_append(reply, &iter);
142
143 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
144 DBUS_TYPE_STRING_AS_STRING,
145 &array_iter);
146
147 if (device->headset &&
148 headset_get_state(device) >= HEADSET_STATE_CONNECTED) {
149 iface = AUDIO_HEADSET_INTERFACE;
150 dbus_message_iter_append_basic(&array_iter,
151 DBUS_TYPE_STRING, &iface);
152 }
153
154 dbus_message_iter_close_container(&iter, &array_iter);
155
156 return reply;
157 }
158
159 static GDBusMethodTable device_methods[] = {
160 { "GetAddress", "", "s", device_get_address },
161 { "GetName", "", "s", device_get_name },
162 { "GetAdapter", "", "s", device_get_adapter },
163 { "GetConnectedInterfaces", "", "as", device_get_connected },
164 { }
165 };
166
device_free(struct audio_device * dev)167 static void device_free(struct audio_device *dev)
168 {
169 if (dev->headset)
170 headset_free(dev);
171
172 if (dev->sink)
173 sink_free(dev);
174
175 if (dev->control)
176 control_free(dev);
177
178 if (dev->conn)
179 dbus_connection_unref(dev->conn);
180
181 if (dev->control_timer)
182 g_source_remove(dev->control_timer);
183
184 g_free(dev->adapter_path);
185 g_free(dev->path);
186 g_free(dev->name);
187
188 g_free(dev);
189 }
190
device_unregister(void * data)191 static void device_unregister(void *data)
192 {
193 struct audio_device *device = data;
194
195 info("Unregistered device path:%s", device->path);
196
197 device_free(device);
198 }
199
control_connect_timeout(gpointer user_data)200 static gboolean control_connect_timeout(gpointer user_data)
201 {
202 struct audio_device *dev = user_data;
203
204 dev->control_timer = 0;
205
206 if (dev->control)
207 avrcp_connect(dev);
208
209 return FALSE;
210 }
211
device_set_control_timer(struct audio_device * dev)212 gboolean device_set_control_timer(struct audio_device *dev)
213 {
214 if (!dev->control)
215 return FALSE;
216
217 if (dev->control_timer)
218 return FALSE;
219
220 dev->control_timer = g_timeout_add_seconds(CONTROL_CONNECT_TIMEOUT,
221 control_connect_timeout,
222 dev);
223
224 return TRUE;
225 }
226
device_remove_control_timer(struct audio_device * dev)227 void device_remove_control_timer(struct audio_device *dev)
228 {
229 if (dev->control_timer)
230 g_source_remove(dev->control_timer);
231 dev->control_timer = 0;
232 }
233
device_register(DBusConnection * conn,const char * path,const bdaddr_t * bda)234 struct audio_device *device_register(DBusConnection *conn,
235 const char *path, const bdaddr_t *bda)
236 {
237 struct audio_device *dev;
238 bdaddr_t src;
239 int dev_id;
240
241 if (!conn || !path)
242 return NULL;
243
244 bacpy(&src, BDADDR_ANY);
245 dev_id = hci_get_route(&src);
246 if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0))
247 return NULL;
248
249 dev = g_new0(struct audio_device, 1);
250
251 /* FIXME just to maintain compatibility */
252 dev->adapter_path = g_strdup_printf("/org/bluez/hci%d", dev_id);
253 if (!dev->adapter_path) {
254 device_free(dev);
255 return NULL;
256 }
257
258 if (!g_dbus_register_interface(conn, path,
259 AUDIO_DEVICE_INTERFACE,
260 device_methods, NULL, NULL,
261 dev, device_unregister)) {
262 error("Failed to register %s interface to %s",
263 AUDIO_DEVICE_INTERFACE, path);
264 device_free(dev);
265 return NULL;
266 }
267
268 dev->name = get_dev_name(conn, &src, bda);
269 dev->path = g_strdup(path);
270 bacpy(&dev->dst, bda);
271 bacpy(&dev->src, &src);
272 bacpy(&dev->store, &src);
273 dev->conn = dbus_connection_ref(conn);
274
275 return dev;
276 }
277
device_store(struct audio_device * dev,gboolean is_default)278 int device_store(struct audio_device *dev, gboolean is_default)
279 {
280 char value[64];
281 char filename[PATH_MAX + 1];
282 char src_addr[18], dst_addr[18];
283 int offset = 0;
284
285 if (!dev->path)
286 return -EINVAL;
287
288 ba2str(&dev->dst, dst_addr);
289 ba2str(&dev->store, src_addr);
290
291 create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "audio");
292 create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
293
294 if (is_default)
295 textfile_put(filename, "default", dst_addr);
296 if (dev->headset) {
297 snprintf(value, 64, "headset ");
298 offset += strlen("headset ");
299 }
300 if (dev->gateway) {
301 snprintf(value + offset, 64 - offset, "gateway ");
302 offset += strlen("gateway ");
303 }
304 if (dev->sink) {
305 snprintf(value + offset, 64 - offset, "sink ");
306 offset += strlen("sink ");
307 }
308 if (dev->source) {
309 snprintf(value + offset, 64 - offset, "source ");
310 offset += strlen("source ");
311 }
312 if (dev->control) {
313 snprintf(value + offset, 64 - offset, "control ");
314 offset += strlen("control ");
315 }
316 if (dev->target)
317 snprintf(value + offset, 64 - offset, "target");
318
319 return textfile_put(filename, dst_addr, value);
320 }
321
device_remove_stored(struct audio_device * dev)322 int device_remove_stored(struct audio_device *dev)
323 {
324 char filename[PATH_MAX + 1];
325 char src_addr[18], dst_addr[18];
326
327 ba2str(&dev->dst, dst_addr);
328 ba2str(&dev->store, src_addr);
329
330 create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "audio");
331
332 return textfile_del(filename, dst_addr);
333 }
334
device_finish_sdp_transaction(struct audio_device * dev)335 void device_finish_sdp_transaction(struct audio_device *dev)
336 {
337 char address[18], *addr_ptr = address;
338 DBusMessage *msg;
339
340 ba2str(&dev->dst, address);
341
342 msg = dbus_message_new_method_call("org.bluez", dev->adapter_path,
343 "org.bluez.Adapter",
344 "FinishRemoteServiceTransaction");
345 if (!msg) {
346 error("Unable to allocate new method call");
347 return;
348 }
349
350 dbus_message_append_args(msg, DBUS_TYPE_STRING, &addr_ptr,
351 DBUS_TYPE_INVALID);
352
353 dbus_connection_send(dev->conn, msg, NULL);
354
355 dbus_message_unref(msg);
356 }
357
358 #if 0
359 static avdtp_state_t ipc_to_avdtp_state(uint8_t ipc_state)
360 {
361 switch (ipc_state) {
362 case STATE_DISCONNECTED:
363 return AVDTP_STATE_IDLE;
364 case STATE_CONNECTING:
365 return AVDTP_STATE_CONFIGURED;
366 case STATE_CONNECTED:
367 return AVDTP_STATE_OPEN;
368 case STATE_STREAM_STARTING:
369 case STATE_STREAMING:
370 return AVDTP_STATE_STREAMING;
371 default:
372 error("Unknown ipc state");
373 return AVDTP_STATE_IDLE;
374 }
375 }
376
377 static headset_state_t ipc_to_hs_state(uint8_t ipc_state)
378 {
379 switch (ipc_state) {
380 case STATE_DISCONNECTED:
381 return HEADSET_STATE_DISCONNECTED;
382 case STATE_CONNECTING:
383 return HEADSET_STATE_CONNECT_IN_PROGRESS;
384 case STATE_CONNECTED:
385 return HEADSET_STATE_CONNECTED;
386 case STATE_STREAM_STARTING:
387 return HEADSET_STATE_PLAY_IN_PROGRESS;
388 case STATE_STREAMING:
389 return HEADSET_STATE_PLAYING;
390 default:
391 error("Unknown ipc state");
392 return HEADSET_STATE_DISCONNECTED;
393 }
394 }
395
396 static uint8_t avdtp_to_ipc_state(avdtp_state_t state)
397 {
398 switch (state) {
399 case AVDTP_STATE_IDLE:
400 return STATE_DISCONNECTED;
401 case AVDTP_STATE_CONFIGURED:
402 return STATE_CONNECTING;
403 case AVDTP_STATE_OPEN:
404 return STATE_CONNECTED;
405 case AVDTP_STATE_STREAMING:
406 return STATE_STREAMING;
407 default:
408 error("Unknown avdt state");
409 return AVDTP_STATE_IDLE;
410 }
411 }
412
413 static uint8_t hs_to_ipc_state(headset_state_t state)
414 {
415 switch (state) {
416 case HEADSET_STATE_DISCONNECTED:
417 return STATE_DISCONNECTED;
418 case HEADSET_STATE_CONNECT_IN_PROGRESS:
419 return STATE_CONNECTING;
420 case HEADSET_STATE_CONNECTED:
421 return STATE_CONNECTED;
422 case HEADSET_STATE_PLAY_IN_PROGRESS:
423 return STATE_STREAMING;
424 default:
425 error("Unknown headset state");
426 return AVDTP_STATE_IDLE;
427 }
428 }
429
430 uint8_t device_get_state(struct audio_device *dev)
431 {
432 avdtp_state_t sink_state;
433 headset_state_t hs_state;
434
435 if (dev->sink && sink_is_active(dev)) {
436 sink_state = sink_get_state(dev);
437 return avdtp_to_ipc_state(sink_state);
438 }
439 else if (dev->headset && headset_is_active(dev)) {
440 hs_state = headset_get_state(dev);
441 return hs_to_ipc_state(hs_state);
442 }
443 else if (dev->control && control_is_active(dev))
444 return STATE_CONNECTED;
445
446 return STATE_DISCONNECTED;
447 }
448 #endif
449
device_is_connected(struct audio_device * dev,const char * interface)450 gboolean device_is_connected(struct audio_device *dev, const char *interface)
451 {
452 if (!interface) {
453 if ((dev->sink || dev->source) &&
454 avdtp_is_connected(&dev->src, &dev->dst))
455 return TRUE;
456
457 if (dev->headset && headset_is_active(dev))
458 return TRUE;
459 }
460 else if (!strcmp(interface, AUDIO_SINK_INTERFACE) && dev->sink &&
461 avdtp_is_connected(&dev->src, &dev->dst))
462 return TRUE;
463 else if (!strcmp(interface, AUDIO_SOURCE_INTERFACE) && dev->source &&
464 avdtp_is_connected(&dev->src, &dev->dst))
465 return TRUE;
466 else if (!strcmp(interface, AUDIO_HEADSET_INTERFACE) && dev->headset &&
467 headset_is_active(dev))
468 return TRUE;
469 else if (!strcmp(interface, AUDIO_CONTROL_INTERFACE) && dev->control &&
470 control_is_active(dev))
471 return TRUE;
472
473 return FALSE;
474 }
475