From a53371133fb399bd7fc70c131a82b64e7e20bac8 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 22 Jun 2007 20:30:35 +0000 Subject: Add device files that implements org.bluez.audio.Device interface. --- audio/device.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ audio/device.h | 73 +++++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 audio/device.c create mode 100644 audio/device.h diff --git a/audio/device.c b/audio/device.c new file mode 100644 index 00000000..88edfc70 --- /dev/null +++ b/audio/device.c @@ -0,0 +1,201 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include + +#include "dbus.h" +#include "dbus-helper.h" +#include "logging.h" + +#include "device.h" + +void device_finish_sdp_transaction(struct device *device) +{ + char address[18], *addr_ptr = address; + DBusMessage *msg, *reply; + DBusError derr; + + ba2str(&device->bda, address); + + msg = dbus_message_new_method_call("org.bluez", device->adapter_path, + "org.bluez.Adapter", + "FinishRemoteServiceTransaction"); + if (!msg) { + error("Unable to allocate new method call"); + return; + } + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &addr_ptr, + DBUS_TYPE_INVALID); + + dbus_error_init(&derr); + reply = dbus_connection_send_with_reply_and_block(device->conn, msg, -1, + &derr); + + dbus_message_unref(msg); + + if (dbus_error_is_set(&derr) || + dbus_set_error_from_message(&derr, reply)) { + error("FinishRemoteServiceTransaction(%s) failed: %s", + address, derr.message); + dbus_error_free(&derr); + return; + } + + dbus_message_unref(reply); +} + +static DBusHandlerResult device_get_address(DBusConnection *conn, + DBusMessage *msg, + void *data) +{ + struct device *device = data; + DBusMessage *reply; + char address[18], *ptr = address; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + ba2str(&device->bda, address); + + dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr, + DBUS_TYPE_INVALID); + + return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult device_get_connected(DBusConnection *conn, + DBusMessage *msg, + void *data) +{ + DBusMessageIter iter, array_iter; + struct device *device = data; + DBusMessage *reply; + const char *iface; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_iter_init_append(reply, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array_iter); + + if (device->headset && + headset_get_state(device->headset) >= HEADSET_STATE_CONNECTED) { + iface = AUDIO_HEADSET_INTERFACE; + dbus_message_iter_append_basic(&array_iter, + DBUS_TYPE_STRING, &iface); + } + + dbus_message_iter_close_container(&iter, &array_iter); + + return send_message_and_unref(conn, reply); +} + +static DBusMethodVTable device_methods[] = { + { "GetAddress", device_get_address, + "", "s" }, + { "GetConnectedInterfaces", device_get_connected, + "", "s" }, + { NULL, NULL, NULL, NULL } +}; + +static void device_free(struct device *device) +{ + if (device->headset) + headset_free(device); + + if (device->conn) + dbus_connection_unref(device->conn); + + if (device->adapter_path) + g_free(device->adapter_path); + + if (device->path) + g_free(device->path); + + g_free(device); +} + +static void device_unregister(DBusConnection *conn, void *data) +{ + struct device *device = data; + + info("Unregistered device path:%s", device->path); + + device_free(device); +} + +struct device * device_register(DBusConnection *conn, const char *path, bdaddr_t *bda) +{ + struct device *device; + bdaddr_t src; + int dev_id; + + if (!conn || !path) + return NULL; + + bacpy(&src, BDADDR_ANY); + dev_id = hci_get_route(NULL); + if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) + return NULL; + + device = g_new0(struct device, 1); + + if (!dbus_connection_create_object_path(conn, path, device, + device_unregister)) { + error("D-Bus failed to register %s path", path); + device_free(device); + return NULL; + } + + if (!dbus_connection_register_interface(conn, + path, + AUDIO_DEVICE_INTERFACE, + device_methods, NULL, NULL)) { + error("Failed to register %s interface to %s", + AUDIO_DEVICE_INTERFACE, path); + dbus_connection_destroy_object_path(conn, path); + return NULL; + } + + device->path = g_strdup(path); + bacpy(&device->bda, bda); + device->conn = dbus_connection_ref(conn); + device->adapter_path = g_malloc0(16); + snprintf(device->adapter_path, 16, "/org/bluez/hci%d", dev_id); + + return device; +} diff --git a/audio/device.h b/audio/device.h new file mode 100644 index 00000000..1a9fd520 --- /dev/null +++ b/audio/device.h @@ -0,0 +1,73 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include "headset.h" +#include "gateway.h" + +#define AUDIO_DEVICE_INTERFACE "org.bluez.audio.Device" + +#define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805F9B34FB" + +#define HSP_HS_UUID "00001108-0000-1000-8000-00805F9B34FB" +#define HSP_AG_UUID "00001112-0000-1000-8000-00805F9B34FB" + +#define HFP_HS_UUID "0000111E-0000-1000-8000-00805F9B34FB" +#define HFP_AG_UUID "0000111F-0000-1000-8000-00805F9B34FB" + +#define ADVANCED_AUDIO_UUID "0000110D-0000-1000-8000-00805F9B34FB" + +#define A2DP_SOURCE_UUID "0000110A-0000-1000-8000-00805F9B34FB" +#define A2DP_SINK_UUID "0000110B-0000-1000-8000-00805F9B34FB" + +#define AVRCP_REMOTE_UUID "0000110E-0000-1000-8000-00805F9B34FB" +#define AVRCP_TARGET_UUID "0000110C-0000-1000-8000-00805F9B34FB" + +/* Move these to respective .h files once they exist */ +#define AUDIO_SINK_INTERFACE "org.bluez.audio.Sink" +#define AUDIO_SOURCE_INTERFACE "org.bluez.audio.Source" +#define AUDIO_CONTROL_INTERFACE "org.bluez.audio.Control" +#define AUDIO_TARGET_INTERFACE "org.bluez.audio.Target" +struct sink; +struct source; +struct control; +struct target; + +struct device { + DBusConnection *conn; + char *adapter_path; + char *path; + bdaddr_t bda; + + struct headset *headset; + struct gateway *gateway; + struct sink *sink; + struct source *source; + struct control *control; + struct target *target; +}; + +struct device *device_register(DBusConnection *conn, const char *path, + bdaddr_t *bda); +void device_finish_sdp_transaction(struct device *device); -- cgit