device.c revision a79bcc5733cb5898abb878fb3cfe8ba27fef7bdf
1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2004-2007  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 <unistd.h>
31#include <sys/stat.h>
32#include <netinet/in.h>
33
34#include <glib.h>
35#include <dbus/dbus.h>
36
37#include <bluetooth/bluetooth.h>
38#include <bluetooth/hci.h>
39#include <bluetooth/hci_lib.h>
40#include <bluetooth/sdp.h>
41#include <bluetooth/sdp_lib.h>
42
43#include "dbus.h"
44#include "dbus-helper.h"
45#include "logging.h"
46#include "textfile.h"
47
48#include "ipc.h"
49#include "device.h"
50#include "avdtp.h"
51#include "headset.h"
52#include "sink.h"
53
54static DBusHandlerResult device_get_address(DBusConnection *conn,
55						DBusMessage *msg, void *data)
56{
57	struct device *device = data;
58	DBusMessage *reply;
59	char address[18], *ptr = address;
60
61	reply = dbus_message_new_method_return(msg);
62	if (!reply)
63		return DBUS_HANDLER_RESULT_NEED_MEMORY;
64
65	ba2str(&device->dst, address);
66
67	dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr,
68							DBUS_TYPE_INVALID);
69
70	return send_message_and_unref(conn, reply);
71}
72
73static DBusHandlerResult device_get_connected(DBusConnection *conn,
74						DBusMessage *msg, void *data)
75{
76	DBusMessageIter iter, array_iter;
77	struct device *device = data;
78	DBusMessage *reply;
79	const char *iface;
80
81	reply = dbus_message_new_method_return(msg);
82	if (!reply)
83		return DBUS_HANDLER_RESULT_NEED_MEMORY;
84
85	dbus_message_iter_init_append(reply, &iter);
86
87	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
88						DBUS_TYPE_STRING_AS_STRING,
89						&array_iter);
90
91	if (device->headset &&
92			headset_get_state(device) >= HEADSET_STATE_CONNECTED) {
93		iface = AUDIO_HEADSET_INTERFACE;
94		dbus_message_iter_append_basic(&array_iter,
95						DBUS_TYPE_STRING, &iface);
96	}
97
98	dbus_message_iter_close_container(&iter, &array_iter);
99
100	return send_message_and_unref(conn, reply);
101}
102
103static DBusMethodVTable device_methods[] = {
104	{ "GetAddress",			device_get_address,	"",	"s" },
105	{ "GetConnectedInterfaces",	device_get_connected,	"",	"s" },
106	{ NULL, NULL, NULL, NULL }
107};
108
109static void device_free(struct device *dev)
110{
111	if (dev->headset)
112		headset_free(dev);
113
114	if (dev->sink)
115		sink_free(dev);
116
117	if (dev->conn)
118		dbus_connection_unref(dev->conn);
119
120	if (dev->adapter_path)
121		g_free(dev->adapter_path);
122
123	if (dev->path)
124		g_free(dev->path);
125
126	g_free(dev);
127}
128
129static void device_unregister(DBusConnection *conn, void *data)
130{
131	struct device *device = data;
132
133	info("Unregistered device path:%s", device->path);
134
135	device_free(device);
136}
137
138char *find_adapter(DBusConnection *conn, bdaddr_t *src)
139{
140	DBusMessage *msg, *reply;
141	DBusError derr;
142	char address[18], *addr_ptr = address;
143	char *path, *ret;
144
145	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
146						"org.bluez.Manager",
147						"FindAdapter");
148	if (!msg) {
149		error("Unable to allocate new method call");
150		return NULL;
151	}
152
153	ba2str(src, address);
154
155	dbus_message_append_args(msg, DBUS_TYPE_STRING, &addr_ptr,
156				 DBUS_TYPE_INVALID);
157
158	dbus_error_init(&derr);
159	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1,
160								&derr);
161
162	dbus_message_unref(msg);
163
164	if (dbus_error_is_set(&derr) ||
165				dbus_set_error_from_message(&derr, reply)) {
166		error("FindAdapter(%s) failed: %s", address, derr.message);
167		dbus_error_free(&derr);
168		return NULL;
169	}
170
171	dbus_error_init(&derr);
172	dbus_message_get_args(reply, &derr,
173				DBUS_TYPE_STRING, &path,
174				DBUS_TYPE_INVALID);
175
176	if (dbus_error_is_set(&derr)) {
177		error("Unable to get message args");
178		dbus_message_unref(reply);
179		dbus_error_free(&derr);
180		return FALSE;
181	}
182
183	ret = g_strdup(path);
184
185	dbus_message_unref(reply);
186
187	debug("Got path %s for adapter with address %s", ret, address);
188
189	return ret;
190}
191
192struct device *device_register(DBusConnection *conn,
193					const char *path, bdaddr_t *bda)
194{
195	struct device *dev;
196	bdaddr_t src;
197	int dev_id;
198	char *adapter_path;
199
200	if (!conn || !path)
201		return NULL;
202
203	bacpy(&src, BDADDR_ANY);
204	dev_id = hci_get_route(&src);
205	if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0))
206		return NULL;
207
208	adapter_path = find_adapter(conn, &src);
209	if (!adapter_path)
210		return NULL;
211
212	dev = g_new0(struct device, 1);
213
214	if (!dbus_connection_create_object_path(conn, path, dev,
215							device_unregister)) {
216		error("D-Bus failed to register %s path", path);
217		device_free(dev);
218		return NULL;
219	}
220
221	if (!dbus_connection_register_interface(conn, path,
222			AUDIO_DEVICE_INTERFACE, device_methods, NULL, NULL)) {
223		error("Failed to register %s interface to %s",
224					AUDIO_DEVICE_INTERFACE, path);
225		dbus_connection_destroy_object_path(conn, path);
226		return NULL;
227	}
228
229	dev->path = g_strdup(path);
230	bacpy(&dev->dst, bda);
231	bacpy(&dev->src, &src);
232	dev->conn = dbus_connection_ref(conn);
233	dev->adapter_path = adapter_path;
234
235	return dev;
236}
237
238int device_store(struct device *dev, gboolean is_default)
239{
240	char value[64];
241	char filename[PATH_MAX + 1];
242	char src_addr[18], dst_addr[18];
243	int offset = 0;
244
245	if (!dev->path)
246		return -EINVAL;
247
248	ba2str(&dev->dst, dst_addr);
249	ba2str(&dev->src, src_addr);
250
251	create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "audio");
252	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
253
254	if (is_default)
255		textfile_put(filename, "default", dst_addr);
256	if (dev->headset) {
257		snprintf(value, 64, "headset ");
258		offset += strlen("headset ");
259	}
260	if (dev->gateway) {
261		snprintf(value + offset, 64 - offset, "gateway ");
262		offset += strlen("gateway ");
263	}
264	if (dev->sink) {
265		snprintf(value + offset, 64 - offset, "sink ");
266		offset += strlen("sink ");
267	}
268	if (dev->source) {
269		snprintf(value + offset, 64 - offset, "source ");
270		offset += strlen("source ");
271	}
272	if (dev->control) {
273		snprintf(value + offset, 64 - offset, "control ");
274		offset += strlen("control ");
275	}
276	if (dev->target)
277		snprintf(value + offset, 64 - offset, "target");
278
279	return textfile_put(filename, dst_addr, value);
280}
281
282int device_remove_stored(struct device *dev)
283{
284	char filename[PATH_MAX + 1];
285	char src_addr[18], dst_addr[18];
286
287	ba2str(&dev->dst, dst_addr);
288	ba2str(&dev->src, src_addr);
289
290	create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "audio");
291
292	return textfile_del(filename, dst_addr);
293}
294
295void device_finish_sdp_transaction(struct device *dev)
296{
297	char address[18], *addr_ptr = address;
298	DBusMessage *msg, *reply;
299	DBusError derr;
300
301	ba2str(&dev->dst, address);
302
303	msg = dbus_message_new_method_call("org.bluez", dev->adapter_path,
304						"org.bluez.Adapter",
305						"FinishRemoteServiceTransaction");
306	if (!msg) {
307		error("Unable to allocate new method call");
308		return;
309	}
310
311	dbus_message_append_args(msg, DBUS_TYPE_STRING, &addr_ptr,
312				 DBUS_TYPE_INVALID);
313
314	dbus_error_init(&derr);
315	reply = dbus_connection_send_with_reply_and_block(dev->conn,
316							msg, -1, &derr);
317
318	dbus_message_unref(msg);
319
320	if (dbus_error_is_set(&derr) ||
321				dbus_set_error_from_message(&derr, reply)) {
322		error("FinishRemoteServiceTransaction(%s) failed: %s",
323						address, derr.message);
324		dbus_error_free(&derr);
325		return;
326	}
327
328	dbus_message_unref(reply);
329}
330
331int device_get_config(struct device *dev, int sock, struct ipc_packet *req,
332			int pkt_len, struct ipc_data_cfg **rsp, int *fd)
333{
334	if (dev->sink && sink_is_active(dev))
335		return sink_get_config(dev, sock, req, pkt_len, rsp, fd);
336	else if (dev->headset && headset_is_active(dev))
337		return headset_get_config(dev, sock, req, pkt_len, rsp, fd);
338	else if (dev->sink)
339		return sink_get_config(dev, sock, req, pkt_len, rsp, fd);
340	else if (dev->headset)
341		return headset_get_config(dev, sock, req, pkt_len, rsp, fd);
342
343	return -EINVAL;
344}
345
346static avdtp_state_t ipc_to_avdtp_state(uint8_t ipc_state)
347{
348	switch (ipc_state) {
349	case STATE_DISCONNECTED:
350		return AVDTP_STATE_IDLE;
351	case STATE_CONNECTING:
352		return AVDTP_STATE_CONFIGURED;
353	case STATE_CONNECTED:
354		return AVDTP_STATE_OPEN;
355	case STATE_STREAM_STARTING:
356	case STATE_STREAMING:
357		return AVDTP_STATE_STREAMING;
358	default:
359		error("Unknown ipc state");
360		return AVDTP_STATE_IDLE;
361	}
362}
363
364static headset_state_t ipc_to_hs_state(uint8_t ipc_state)
365{
366	switch (ipc_state) {
367	case STATE_DISCONNECTED:
368		return HEADSET_STATE_DISCONNECTED;
369	case STATE_CONNECTING:
370		return HEADSET_STATE_CONNECT_IN_PROGRESS;
371	case STATE_CONNECTED:
372		return HEADSET_STATE_CONNECTED;
373	case STATE_STREAM_STARTING:
374		return HEADSET_STATE_PLAY_IN_PROGRESS;
375	case STATE_STREAMING:
376		return HEADSET_STATE_PLAYING;
377	default:
378		error("Unknown ipc state");
379		return HEADSET_STATE_DISCONNECTED;
380	}
381}
382
383void device_set_state(struct device *dev, uint8_t state)
384{
385	if (dev->sink && sink_is_active(dev))
386		sink_set_state(dev, ipc_to_avdtp_state(state));
387	else if (dev->headset && headset_is_active(dev))
388		headset_set_state(dev, ipc_to_hs_state(state));
389}
390
391static uint8_t avdtp_to_ipc_state(avdtp_state_t state)
392{
393	switch (state) {
394	case AVDTP_STATE_IDLE:
395		return STATE_DISCONNECTED;
396	case AVDTP_STATE_CONFIGURED:
397		return STATE_CONNECTING;
398	case AVDTP_STATE_OPEN:
399		return STATE_CONNECTED;
400	case AVDTP_STATE_STREAMING:
401		return STATE_STREAMING;
402	default:
403		error("Unknown avdt state");
404		return AVDTP_STATE_IDLE;
405	}
406}
407
408static uint8_t hs_to_ipc_state(headset_state_t state)
409{
410	switch (state) {
411	case HEADSET_STATE_DISCONNECTED:
412		return STATE_DISCONNECTED;
413	case HEADSET_STATE_CONNECT_IN_PROGRESS:
414		return STATE_CONNECTING;
415	case HEADSET_STATE_CONNECTED:
416		return STATE_CONNECTED;
417	case HEADSET_STATE_PLAY_IN_PROGRESS:
418		return STATE_STREAMING;
419	default:
420		error("Unknown headset state");
421		return AVDTP_STATE_IDLE;
422	}
423}
424
425uint8_t device_get_state(struct device *dev)
426{
427	avdtp_state_t sink_state;
428	headset_state_t hs_state;
429
430	if (dev->sink && sink_is_active(dev)) {
431		sink_state = sink_get_state(dev);
432		return avdtp_to_ipc_state(sink_state);
433	}
434	else if (dev->headset && headset_is_active(dev)) {
435		hs_state = headset_get_state(dev);
436		return hs_to_ipc_state(hs_state);
437	}
438
439	return STATE_DISCONNECTED;
440}
441