diff options
Diffstat (limited to 'cras/src/server/cras_bt_profile.c')
-rw-r--r-- | cras/src/server/cras_bt_profile.c | 479 |
1 files changed, 0 insertions, 479 deletions
diff --git a/cras/src/server/cras_bt_profile.c b/cras/src/server/cras_bt_profile.c deleted file mode 100644 index 9b4171fa..00000000 --- a/cras/src/server/cras_bt_profile.c +++ /dev/null @@ -1,479 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <dbus/dbus.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> - -#include "cras_bt_constants.h" -#include "cras_bt_device.h" -#include "cras_bt_profile.h" -#include "cras_dbus_util.h" -#include "utlist.h" - -#define PROFILE_INTROSPECT_XML \ - DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \ - "<node>\n" \ - " <interface name=\"org.bluez.Profile1\">\n" \ - " <method name=\"Release\">\n" \ - " </method>\n" \ - " <method name=\"NewConnection\">\n" \ - " <arg name=\"device\" type=\"o\" direction=\"in\">\n" \ - " <arg name=\"fd\" type=\"h\" direction=\"in\">\n" \ - " <arg name=\"fd_properties\" type=\"a{sv}\" direction=\"in\">\n" \ - " </method>\n" \ - " <method name=\"RequestDisconnection\">\n" \ - " <arg name=\"device\" type=\"o\" direction=\"in\">\n" \ - " </method>\n" \ - " <method name=\"Cancel\">\n" \ - " </method>\n" \ - " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n" \ - " <method name=\"Introspect\">\n" \ - " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \ - " </method>\n" \ - " </interface>\n" \ - "</node>\n" - -/* Profiles */ -static struct cras_bt_profile *profiles; - -static DBusHandlerResult cras_bt_profile_handle_release(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - DBusMessage *reply; - const char *profile_path; - struct cras_bt_profile *profile; - - profile_path = dbus_message_get_path(message); - - profile = cras_bt_profile_get(profile_path); - if (!profile) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - syslog(LOG_ERR, "Profile %s released by bluetoothd", profile->name); - profile->release(profile); - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (!dbus_connection_send(conn, reply, NULL)) { - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - - dbus_message_unref(reply); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult -cras_bt_profile_handle_new_connection(DBusConnection *conn, - DBusMessage *message, void *arg) -{ - DBusMessageIter message_iter; - DBusMessage *reply; - const char *profile_path, *object_path; - int fd = -1; - int err; - struct cras_bt_profile *profile; - struct cras_bt_device *device; - - profile_path = dbus_message_get_path(message); - - dbus_message_iter_init(message, &message_iter); - dbus_message_iter_get_basic(&message_iter, &object_path); - dbus_message_iter_next(&message_iter); - - if (dbus_message_iter_get_arg_type(&message_iter) != - DBUS_TYPE_UNIX_FD) { - syslog(LOG_ERR, "Argument not a valid unix file descriptor"); - goto invalid; - } - - dbus_message_iter_get_basic(&message_iter, &fd); - dbus_message_iter_next(&message_iter); - if (fd < 0) - goto invalid; - - profile = cras_bt_profile_get(profile_path); - if (!profile) - goto invalid; - - device = cras_bt_device_get(object_path); - if (!device) { - syslog(LOG_ERR, "Device %s not found at %s new connection", - object_path, profile_path); - device = cras_bt_device_create(conn, object_path); - } - - err = profile->new_connection(conn, profile, device, fd); - if (err) { - syslog(LOG_INFO, "%s new connection rejected", profile->name); - close(fd); - reply = dbus_message_new_error( - message, "org.chromium.Cras.Error.RejectNewConnection", - "Possibly another headset already in use"); - if (!dbus_connection_send(conn, reply, NULL)) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_HANDLED; - } - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (!dbus_connection_send(conn, reply, NULL)) { - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_HANDLED; - -invalid: - if (fd >= 0) - close(fd); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult -cras_bt_profile_handle_request_disconnection(DBusConnection *conn, - DBusMessage *message, void *arg) -{ - DBusMessageIter message_iter; - DBusMessage *reply; - const char *prpofile_path, *object_path; - struct cras_bt_profile *profile; - struct cras_bt_device *device; - - prpofile_path = dbus_message_get_path(message); - - dbus_message_iter_init(message, &message_iter); - dbus_message_iter_get_basic(&message_iter, &object_path); - dbus_message_iter_next(&message_iter); - - profile = cras_bt_profile_get(prpofile_path); - if (!profile) - goto invalid; - - device = cras_bt_device_get(object_path); - if (!device) - goto invalid; - - profile->request_disconnection(profile, device); - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (!dbus_connection_send(conn, reply, NULL)) { - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - - dbus_message_unref(reply); - - return DBUS_HANDLER_RESULT_HANDLED; - -invalid: - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult cras_bt_profile_handle_cancel(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - DBusMessage *reply; - const char *profile_path; - struct cras_bt_profile *profile; - - profile_path = dbus_message_get_path(message); - - profile = cras_bt_profile_get(profile_path); - if (!profile) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - profile->cancel(profile); - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (!dbus_connection_send(conn, reply, NULL)) { - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - - dbus_message_unref(reply); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult cras_bt_handle_profile_messages(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, - "Introspect")) { - DBusMessage *reply; - const char *xml = PROFILE_INTROSPECT_XML; - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &xml, - DBUS_TYPE_INVALID)) { - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - if (!dbus_connection_send(conn, reply, NULL)) { - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_method_call(message, BLUEZ_INTERFACE_PROFILE, - "Release")) { - return cras_bt_profile_handle_release(conn, message, arg); - } else if (dbus_message_is_method_call(message, BLUEZ_INTERFACE_PROFILE, - "NewConnection")) { - return cras_bt_profile_handle_new_connection(conn, message, - arg); - } else if (dbus_message_is_method_call(message, BLUEZ_INTERFACE_PROFILE, - "RequestDisconnection")) { - return cras_bt_profile_handle_request_disconnection( - conn, message, arg); - } else if (dbus_message_is_method_call(message, BLUEZ_INTERFACE_PROFILE, - "Cancel")) { - return cras_bt_profile_handle_cancel(conn, message, arg); - } else { - syslog(LOG_ERR, "Unknown Profile message"); - } - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static void cras_bt_on_register_profile(DBusPendingCall *pending_call, - void *data) -{ - DBusMessage *reply; - - reply = dbus_pending_call_steal_reply(pending_call); - dbus_pending_call_unref(pending_call); - - if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) - syslog(LOG_ERR, "RegisterProfile returned error: %s", - dbus_message_get_error_name(reply)); - dbus_message_unref(reply); -} - -int cras_bt_register_profile(DBusConnection *conn, - struct cras_bt_profile *profile) -{ - DBusMessage *method_call; - DBusMessageIter message_iter; - DBusMessageIter properties_array_iter; - DBusPendingCall *pending_call; - - method_call = dbus_message_new_method_call(BLUEZ_SERVICE, - PROFILE_MANAGER_OBJ_PATH, - BLUEZ_PROFILE_MGMT_INTERFACE, - "RegisterProfile"); - - if (!method_call) - return -ENOMEM; - - dbus_message_iter_init_append(method_call, &message_iter); - dbus_message_iter_append_basic(&message_iter, DBUS_TYPE_OBJECT_PATH, - &profile->object_path); - dbus_message_iter_append_basic(&message_iter, DBUS_TYPE_STRING, - &profile->uuid); - - dbus_message_iter_open_container( - &message_iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &properties_array_iter); - - if (!append_key_value(&properties_array_iter, "Name", DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, &profile->name)) { - dbus_message_unref(method_call); - return -ENOMEM; - } - - if (profile->record && - !append_key_value(&properties_array_iter, "ServiceRecord", - DBUS_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING, - &profile->record)) { - dbus_message_unref(method_call); - return -ENOMEM; - } - - if (!append_key_value(&properties_array_iter, "Version", - DBUS_TYPE_UINT16, DBUS_TYPE_UINT16_AS_STRING, - &profile->version)) { - dbus_message_unref(method_call); - return -ENOMEM; - } - - if (profile->role && - !append_key_value(&properties_array_iter, "Role", DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, &profile->role)) { - dbus_message_unref(method_call); - return -ENOMEM; - } - - if (profile->features && - !append_key_value(&properties_array_iter, "Features", - DBUS_TYPE_UINT16, DBUS_TYPE_UINT16_AS_STRING, - &profile->features)) { - dbus_message_unref(method_call); - return -ENOMEM; - } - - dbus_message_iter_close_container(&message_iter, - &properties_array_iter); - - if (!dbus_connection_send_with_reply(conn, method_call, &pending_call, - DBUS_TIMEOUT_USE_DEFAULT)) { - dbus_message_unref(method_call); - return -ENOMEM; - } - - dbus_message_unref(method_call); - if (!pending_call) - return -EIO; - - if (!dbus_pending_call_set_notify( - pending_call, cras_bt_on_register_profile, NULL, NULL)) { - dbus_pending_call_cancel(pending_call); - dbus_pending_call_unref(pending_call); - syslog(LOG_ERR, "register profile fail on set notify"); - return -ENOMEM; - } - - return 0; -} - -int cras_bt_unregister_profile(DBusConnection *conn, - struct cras_bt_profile *profile) -{ - DBusMessage *method_call; - DBusMessageIter message_iter; - DBusError dbus_error; - DBusMessage *reply; - - method_call = dbus_message_new_method_call(BLUEZ_SERVICE, - PROFILE_MANAGER_OBJ_PATH, - BLUEZ_PROFILE_MGMT_INTERFACE, - "UnregisterProfile"); - - if (!method_call) - return -ENOMEM; - dbus_error_init(&dbus_error); - dbus_message_iter_init_append(method_call, &message_iter); - dbus_message_iter_append_basic(&message_iter, DBUS_TYPE_OBJECT_PATH, - &profile->object_path); - reply = dbus_connection_send_with_reply_and_block( - conn, method_call, DBUS_TIMEOUT_USE_DEFAULT, &dbus_error); - - if (!reply) { - dbus_error_free(&dbus_error); - dbus_message_unref(method_call); - return -EIO; - } - - dbus_message_unref(method_call); - - if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { - syslog(LOG_ERR, "Unregister profile returned error: %s", - dbus_message_get_error_name(reply)); - dbus_message_unref(reply); - return -EIO; - } - dbus_message_unref(reply); - return 0; -} - -int cras_bt_register_profiles(DBusConnection *conn) -{ - struct cras_bt_profile *profile; - int err; - - DL_FOREACH (profiles, profile) { - err = cras_bt_register_profile(conn, profile); - if (err) - return err; - } - - return 0; -} - -int cras_bt_add_profile(DBusConnection *conn, struct cras_bt_profile *profile) -{ - static const DBusObjectPathVTable profile_vtable = { - NULL, cras_bt_handle_profile_messages, NULL, NULL, NULL, NULL - }; - - DBusError dbus_error; - - dbus_error_init(&dbus_error); - - if (!dbus_connection_register_object_path( - conn, profile->object_path, &profile_vtable, &dbus_error)) { - syslog(LOG_ERR, "Could not register BT profile %s: %s", - profile->object_path, dbus_error.message); - dbus_error_free(&dbus_error); - return -ENOMEM; - } - - DL_APPEND(profiles, profile); - - return 0; -} - -int cras_bt_rm_profile(DBusConnection *conn, struct cras_bt_profile *profile) -{ - DL_DELETE(profiles, profile); - - if (!dbus_connection_unregister_object_path(conn, - profile->object_path)) { - syslog(LOG_ERR, "Could not unregister BT profile %s", - profile->object_path); - return -ENOMEM; - } - return 0; -} - -void cras_bt_profile_reset() -{ - struct cras_bt_profile *profile; - - DL_FOREACH (profiles, profile) - profile->release(profile); -} - -struct cras_bt_profile *cras_bt_profile_get(const char *path) -{ - struct cras_bt_profile *profile; - DL_FOREACH (profiles, profile) { - if (strcmp(profile->object_path, path) == 0) - return profile; - } - - return NULL; -} - -void cras_bt_profile_on_device_disconnected(struct cras_bt_device *device) -{ - struct cras_bt_profile *profile; - DL_FOREACH (profiles, profile) - profile->request_disconnection(profile, device); -} |