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