• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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