From patchwork Sat Apr 6 19:55:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis Kenzior X-Patchwork-Id: 13619915 Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E2FC4C618 for ; Sat, 6 Apr 2024 19:55:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712433361; cv=none; b=sE3E3KTlg5o+2/e7IjUohv3ELKLhFkEtyj7Hjuw8JdC3EbwKnIogIOXyWc0P9GX6U9+t6csxoDEKXPAhXXnotnb6wvVvJ2kZncHTNN5IPvwcIn80xo81ZCmNB5QkUFR5SsibBMn3AXA/4PmEgv9oJ0j0j1UMSZnyTOuV1vjK/4Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712433361; c=relaxed/simple; bh=sYimW7uNaazjsYJEINo5KTFlD/tJAP8HgkjeX7+qT5Y=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=sUJ59oOi4+RE5CYG4eRPtYkiwucH2wUlIFepDgpTPJb6wsfZQ8Oa9slcnegxzSYPImMBLRz0xqw1hVX85NRbOv92OlxzR+fVqCQRRt1knGC6BBS5fbF/cUgPQA4At7gCbUVpP4MBAbDr5IiTPvx+RYYdim7Ywp1Y+rvgYhVdDNs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=HucTlTKG; arc=none smtp.client-ip=209.85.160.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HucTlTKG" Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-22ec890ee96so1463851fac.1 for ; Sat, 06 Apr 2024 12:55:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712433355; x=1713038155; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=umCxvv5+wvcT2BdYNfn7E2YdKr3KaefF2RsgeLtv8Jo=; b=HucTlTKGHhI+WLASaltSbnC0bMHkbKdiXlqjGLfjyNQ3+x451sM6XBe07rljhAwPkR ewtqpxlEmEFBLMazdpyiYuW8RPmALgBK9nhUu+hn/t3ugjKOiHG5IK4cAERspRx38m98 234aViTvHFSubBCqG30lFQcI/vfPfoqYm0bYtuicG/I/xTFcx4oEKTbA2LL+NZfF+WWv 1+CGmzZyWEYfbm0xFXuyhyV1Z924AqiK5i6wxJ0GIY44mk3khsPa77HFbHen8ZsfkAF3 8b0WTItLvyLbxy4W4EAePYG43WqUrevRl5sHfXBJkjG6tkbKgMDV3Nyc1f2I8Gh8FZdS CgNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712433355; x=1713038155; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=umCxvv5+wvcT2BdYNfn7E2YdKr3KaefF2RsgeLtv8Jo=; b=vzKtpY9zq67Ajd3juL8ap1duCWGsSl8359SO5xB6rxHbRkHoGRWBhSIHrWiy/135g4 3mASqRzVuPWDjhrPqiS29vnavMuC9oOeFpUrwv+ZmpT+BxvJ/mCK2FuJlzKlQkg9gkAb qdJMTisw6I5VxtFmXor/ddE04Zucn9XYEZDZrh9j8d//nMty5ZgYywtKmZoZ643LCtl4 GRwT39phaiSYN0UGz1MihynTIJ6mM3DYCD9ydkgamYOsgy2Xxry4fVHhsx+ftV5yO91G FZNOPl8Lr2krJZXj9roBXhleudpAhRWXXUNtjwWLoBd680m38ZvjNhpBZyeoObbGH+sN ETuA== X-Gm-Message-State: AOJu0YwXBvKoM8Ia8P9LEWyEe4nBvcLU8GG8qrfyhx7se+85b9j+sdgt lw29E/aNpgwjSLFoFwyOBpTSBhMjMb0AKl+t7OX5ub6VMXQqywDsuqFm3enO X-Google-Smtp-Source: AGHT+IEA6JVpmYMPso6Snkq28C8XJLOGbE31kMzfeckhhRQIzMmvYcuQEGIt/mylDUDjolA8VqOnbQ== X-Received: by 2002:a05:6870:af97:b0:221:4fe5:87cb with SMTP id uz23-20020a056870af9700b002214fe587cbmr7056854oab.42.1712433353750; Sat, 06 Apr 2024 12:55:53 -0700 (PDT) Received: from localhost.localdomain (070-114-247-242.res.spectrum.com. [70.114.247.242]) by smtp.gmail.com with ESMTPSA id gc9-20020a056870678900b0022f0862fb1asm243829oab.40.2024.04.06.12.55.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 06 Apr 2024 12:55:53 -0700 (PDT) From: Denis Kenzior To: ofono@lists.linux.dev Cc: Denis Kenzior Subject: [PATCH] bluez4: Remove support Date: Sat, 6 Apr 2024 14:55:35 -0500 Message-ID: <20240406195550.2950800-1-denkenz@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: ofono@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 BlueZ 5 is now up to release 5.73, with the 5.0 release date being in late 2012. There's very little chance that anyone is using BlueZ 4 anymore. Remove it. --- Makefile.am | 32 +- btio/btio.c | 1447 --------------------------------------- btio/btio.h | 110 --- configure.ac | 1 - dundee/bluez4.c | 296 -------- plugins/bluez4.c | 988 -------------------------- plugins/bluez4.h | 84 --- plugins/dun_gw_bluez4.c | 172 ----- plugins/hfp_ag_bluez4.c | 218 ------ plugins/hfp_hf_bluez4.c | 554 --------------- plugins/sap.c | 363 ---------- 11 files changed, 1 insertion(+), 4264 deletions(-) delete mode 100644 btio/btio.c delete mode 100644 btio/btio.h delete mode 100644 dundee/bluez4.c delete mode 100644 plugins/bluez4.c delete mode 100644 plugins/bluez4.h delete mode 100644 plugins/dun_gw_bluez4.c delete mode 100644 plugins/hfp_ag_bluez4.c delete mode 100644 plugins/hfp_hf_bluez4.c delete mode 100644 plugins/sap.c diff --git a/Makefile.am b/Makefile.am index 3e545e8f11de..9a6f82c39552 100644 --- a/Makefile.am +++ b/Makefile.am @@ -262,8 +262,6 @@ gril_sources = gril/gril.h gril/gril.c \ gril/parcel.c gril/parcel.h \ gril/ril_constants.h -btio_sources = btio/btio.h btio/btio.c - if UDEV builtin_cflags += @UDEV_CFLAGS@ builtin_libadd += @UDEV_LIBS@ @@ -577,16 +575,6 @@ builtin_modules += connman builtin_sources += plugins/connman.c if BLUETOOTH -if BLUEZ4 -builtin_modules += sap -builtin_sources += plugins/sap.c plugins/bluez4.h - -builtin_modules += hfp_bluez4 -builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h - -builtin_modules += dun_gw_bluez4 -builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h -else builtin_modules += hfp_bluez5 builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h @@ -594,26 +582,13 @@ builtin_modules += dun_gw_bluez5 builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h endif endif -endif if BLUETOOTH -if BLUEZ4 -builtin_modules += bluez4 -builtin_sources += plugins/bluez4.c plugins/bluez4.h - -builtin_modules += hfp_ag_bluez4 -builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h - -builtin_sources += $(btio_sources) -builtin_cflags += @BLUEZ_CFLAGS@ -builtin_libadd += @BLUEZ_LIBS@ -else builtin_modules += bluez5 builtin_sources += plugins/bluez5.c plugins/bluez5.h builtin_modules += hfp_ag_bluez5 builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h -endif if UPOWER builtin_modules += upower @@ -709,7 +684,7 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ $(ell_cflags) $(builtin_cflags) \ AM_CPPFLAGS = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/src \ -I$(srcdir)/gdbus -I$(srcdir)/gisi -I$(srcdir)/gatchat \ - -I$(srcdir)/btio -I$(srcdir)/gril + -I$(srcdir)/gril doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \ doc/manager-api.txt doc/modem-api.txt doc/network-api.txt \ @@ -1022,15 +997,10 @@ systemdunit_DATA += dundee/dundee.service endif endif -if BLUEZ4 -dundee_dundee_SOURCES = $(dundee_common_sources) $(btio_sources) \ - plugins/bluez4.c dundee/bluez4.c -else dundee_dundee_SOURCES = $(dundee_common_sources) plugins/bluez5.c \ dundee/bluez5.c endif endif -endif noinst_PROGRAMS += gatchat/gsmdial gatchat/test-server gatchat/test-qcdm diff --git a/btio/btio.c b/btio/btio.c deleted file mode 100644 index 9781ec417ee2..000000000000 --- a/btio/btio.c +++ /dev/null @@ -1,1447 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2009-2010 Marcel Holtmann - * Copyright (C) 2009-2010 Nokia Corporation - * - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "btio.h" - -#ifndef BT_FLUSHABLE -#define BT_FLUSHABLE 8 -#endif - -#define ERROR_FAILED(gerr, str, err) \ - g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED, \ - str ": %s (%d)", strerror(err), err) - -#define DEFAULT_DEFER_TIMEOUT 30 - -struct set_opts { - bdaddr_t src; - bdaddr_t dst; - int defer; - int sec_level; - uint8_t channel; - uint16_t psm; - uint16_t cid; - uint16_t mtu; - uint16_t imtu; - uint16_t omtu; - int master; - uint8_t mode; - int flushable; - uint32_t priority; -}; - -struct connect { - BtIOConnect connect; - gpointer user_data; - GDestroyNotify destroy; -}; - -struct accept { - BtIOConnect connect; - gpointer user_data; - GDestroyNotify destroy; -}; - -struct server { - BtIOConnect connect; - BtIOConfirm confirm; - gpointer user_data; - GDestroyNotify destroy; -}; - -static void server_remove(struct server *server) -{ - if (server->destroy) - server->destroy(server->user_data); - g_free(server); -} - -static void connect_remove(struct connect *conn) -{ - if (conn->destroy) - conn->destroy(conn->user_data); - g_free(conn); -} - -static void accept_remove(struct accept *accept) -{ - if (accept->destroy) - accept->destroy(accept->user_data); - g_free(accept); -} - -static gboolean check_nval(GIOChannel *io) -{ - struct pollfd fds; - - memset(&fds, 0, sizeof(fds)); - fds.fd = g_io_channel_unix_get_fd(io); - fds.events = POLLNVAL; - - if (poll(&fds, 1, 0) > 0 && (fds.revents & POLLNVAL)) - return TRUE; - - return FALSE; -} - -static gboolean accept_cb(GIOChannel *io, GIOCondition cond, - gpointer user_data) -{ - struct accept *accept = user_data; - GError *err = NULL; - - /* If the user aborted this accept attempt */ - if ((cond & G_IO_NVAL) || check_nval(io)) - return FALSE; - - if (cond & (G_IO_HUP | G_IO_ERR)) - g_set_error(&err, BT_IO_ERROR, BT_IO_ERROR_DISCONNECTED, - "HUP or ERR on socket"); - - accept->connect(io, err, accept->user_data); - - g_clear_error(&err); - - return FALSE; -} - -static gboolean connect_cb(GIOChannel *io, GIOCondition cond, - gpointer user_data) -{ - struct connect *conn = user_data; - GError *gerr = NULL; - - /* If the user aborted this connect attempt */ - if ((cond & G_IO_NVAL) || check_nval(io)) - return FALSE; - - if (cond & G_IO_OUT) { - int err, sk_err = 0, sock = g_io_channel_unix_get_fd(io); - socklen_t len = sizeof(sk_err); - - if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0) - err = -errno; - else - err = -sk_err; - - if (err < 0) - g_set_error(&gerr, BT_IO_ERROR, - BT_IO_ERROR_CONNECT_FAILED, "%s (%d)", - strerror(-err), -err); - } else if (cond & (G_IO_HUP | G_IO_ERR)) - g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED, - "HUP or ERR on socket"); - - conn->connect(io, gerr, conn->user_data); - - if (gerr) - g_error_free(gerr); - - return FALSE; -} - -static gboolean server_cb(GIOChannel *io, GIOCondition cond, - gpointer user_data) -{ - struct server *server = user_data; - int srv_sock, cli_sock; - GIOChannel *cli_io; - - /* If the user closed the server */ - if ((cond & G_IO_NVAL) || check_nval(io)) - return FALSE; - - srv_sock = g_io_channel_unix_get_fd(io); - - cli_sock = accept(srv_sock, NULL, NULL); - if (cli_sock < 0) - return TRUE; - - cli_io = g_io_channel_unix_new(cli_sock); - - g_io_channel_set_close_on_unref(cli_io, TRUE); - g_io_channel_set_flags(cli_io, G_IO_FLAG_NONBLOCK, NULL); - - if (server->confirm) - server->confirm(cli_io, server->user_data); - else - server->connect(cli_io, NULL, server->user_data); - - g_io_channel_unref(cli_io); - - return TRUE; -} - -static void server_add(GIOChannel *io, BtIOConnect connect, - BtIOConfirm confirm, gpointer user_data, - GDestroyNotify destroy) -{ - struct server *server; - GIOCondition cond; - - server = g_new0(struct server, 1); - server->connect = connect; - server->confirm = confirm; - server->user_data = user_data; - server->destroy = destroy; - - cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL; - g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, server_cb, server, - (GDestroyNotify) server_remove); -} - -static void connect_add(GIOChannel *io, BtIOConnect connect, - gpointer user_data, GDestroyNotify destroy) -{ - struct connect *conn; - GIOCondition cond; - - conn = g_new0(struct connect, 1); - conn->connect = connect; - conn->user_data = user_data; - conn->destroy = destroy; - - cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL; - g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, connect_cb, conn, - (GDestroyNotify) connect_remove); -} - -static void accept_add(GIOChannel *io, BtIOConnect connect, gpointer user_data, - GDestroyNotify destroy) -{ - struct accept *accept; - GIOCondition cond; - - accept = g_new0(struct accept, 1); - accept->connect = connect; - accept->user_data = user_data; - accept->destroy = destroy; - - cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL; - g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, accept_cb, accept, - (GDestroyNotify) accept_remove); -} - -static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm, - uint16_t cid, GError **err) -{ - struct sockaddr_l2 addr; - - memset(&addr, 0, sizeof(addr)); - addr.l2_family = AF_BLUETOOTH; - bacpy(&addr.l2_bdaddr, src); - - if (cid) - addr.l2_cid = htobs(cid); - else - addr.l2_psm = htobs(psm); - - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - int error = -errno; - ERROR_FAILED(err, "l2cap_bind", errno); - return error; - } - - return 0; -} - -static int l2cap_connect(int sock, const bdaddr_t *dst, - uint16_t psm, uint16_t cid) -{ - int err; - struct sockaddr_l2 addr; - - memset(&addr, 0, sizeof(addr)); - addr.l2_family = AF_BLUETOOTH; - bacpy(&addr.l2_bdaddr, dst); - if (cid) - addr.l2_cid = htobs(cid); - else - addr.l2_psm = htobs(psm); - - err = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) - return -errno; - - return 0; -} - -static int l2cap_set_master(int sock, int master) -{ - int flags; - socklen_t len; - - len = sizeof(flags); - if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, &len) < 0) - return -errno; - - if (master) { - if (flags & L2CAP_LM_MASTER) - return 0; - flags |= L2CAP_LM_MASTER; - } else { - if (!(flags & L2CAP_LM_MASTER)) - return 0; - flags &= ~L2CAP_LM_MASTER; - } - - if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, sizeof(flags)) < 0) - return -errno; - - return 0; -} - -static int rfcomm_set_master(int sock, int master) -{ - int flags; - socklen_t len; - - len = sizeof(flags); - if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, &len) < 0) - return -errno; - - if (master) { - if (flags & RFCOMM_LM_MASTER) - return 0; - flags |= RFCOMM_LM_MASTER; - } else { - if (!(flags & RFCOMM_LM_MASTER)) - return 0; - flags &= ~RFCOMM_LM_MASTER; - } - - if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, sizeof(flags)) < 0) - return -errno; - - return 0; -} - -static int l2cap_set_lm(int sock, int level) -{ - int lm_map[] = { - 0, - L2CAP_LM_AUTH, - L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT, - L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE, - }, opt = lm_map[level]; - - if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) - return -errno; - - return 0; -} - -static int rfcomm_set_lm(int sock, int level) -{ - int lm_map[] = { - 0, - RFCOMM_LM_AUTH, - RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT, - RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE, - }, opt = lm_map[level]; - - if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)) < 0) - return -errno; - - return 0; -} - -static gboolean set_sec_level(int sock, BtIOType type, int level, GError **err) -{ - struct bt_security sec; - int ret; - - if (level < BT_SECURITY_LOW || level > BT_SECURITY_HIGH) { - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Valid security level range is %d-%d", - BT_SECURITY_LOW, BT_SECURITY_HIGH); - return FALSE; - } - - memset(&sec, 0, sizeof(sec)); - sec.level = level; - - if (setsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec, - sizeof(sec)) == 0) - return TRUE; - - if (errno != ENOPROTOOPT) { - ERROR_FAILED(err, "setsockopt(BT_SECURITY)", errno); - return FALSE; - } - - if (type == BT_IO_L2CAP) - ret = l2cap_set_lm(sock, level); - else - ret = rfcomm_set_lm(sock, level); - - if (ret < 0) { - ERROR_FAILED(err, "setsockopt(LM)", -ret); - return FALSE; - } - - return TRUE; -} - -static int l2cap_get_lm(int sock, int *sec_level) -{ - int opt; - socklen_t len; - - len = sizeof(opt); - if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, &len) < 0) - return -errno; - - *sec_level = 0; - - if (opt & L2CAP_LM_AUTH) - *sec_level = BT_SECURITY_LOW; - if (opt & L2CAP_LM_ENCRYPT) - *sec_level = BT_SECURITY_MEDIUM; - if (opt & L2CAP_LM_SECURE) - *sec_level = BT_SECURITY_HIGH; - - return 0; -} - -static int rfcomm_get_lm(int sock, int *sec_level) -{ - int opt; - socklen_t len; - - len = sizeof(opt); - if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, &len) < 0) - return -errno; - - *sec_level = 0; - - if (opt & RFCOMM_LM_AUTH) - *sec_level = BT_SECURITY_LOW; - if (opt & RFCOMM_LM_ENCRYPT) - *sec_level = BT_SECURITY_MEDIUM; - if (opt & RFCOMM_LM_SECURE) - *sec_level = BT_SECURITY_HIGH; - - return 0; -} - -static gboolean get_sec_level(int sock, BtIOType type, int *level, - GError **err) -{ - struct bt_security sec; - socklen_t len; - int ret; - - memset(&sec, 0, sizeof(sec)); - len = sizeof(sec); - if (getsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) == 0) { - *level = sec.level; - return TRUE; - } - - if (errno != ENOPROTOOPT) { - ERROR_FAILED(err, "getsockopt(BT_SECURITY)", errno); - return FALSE; - } - - if (type == BT_IO_L2CAP) - ret = l2cap_get_lm(sock, level); - else - ret = rfcomm_get_lm(sock, level); - - if (ret < 0) { - ERROR_FAILED(err, "getsockopt(LM)", -ret); - return FALSE; - } - - return TRUE; -} - -static int l2cap_set_flushable(int sock, gboolean flushable) -{ - int f; - - f = flushable; - if (setsockopt(sock, SOL_BLUETOOTH, BT_FLUSHABLE, &f, sizeof(f)) < 0) - return -errno; - - return 0; -} - -static int set_priority(int sock, uint32_t prio) -{ - if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0) - return -errno; - - return 0; -} - -static gboolean get_key_size(int sock, int *size, GError **err) -{ - struct bt_security sec; - socklen_t len; - - memset(&sec, 0, sizeof(sec)); - len = sizeof(sec); - if (getsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) == 0) { - *size = sec.key_size; - return TRUE; - } - - return FALSE; -} - -static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu, - uint16_t omtu, uint8_t mode, int master, - int flushable, uint32_t priority, GError **err) -{ - if (imtu || omtu || mode) { - struct l2cap_options l2o; - socklen_t len; - - memset(&l2o, 0, sizeof(l2o)); - len = sizeof(l2o); - if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, - &len) < 0) { - ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno); - return FALSE; - } - - if (imtu) - l2o.imtu = imtu; - if (omtu) - l2o.omtu = omtu; - if (mode) - l2o.mode = mode; - - if (setsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, - sizeof(l2o)) < 0) { - ERROR_FAILED(err, "setsockopt(L2CAP_OPTIONS)", errno); - return FALSE; - } - } - - if (master >= 0 && l2cap_set_master(sock, master) < 0) { - ERROR_FAILED(err, "l2cap_set_master", errno); - return FALSE; - } - - if (flushable >= 0 && l2cap_set_flushable(sock, flushable) < 0) { - ERROR_FAILED(err, "l2cap_set_flushable", errno); - return FALSE; - } - - if (priority > 0 && set_priority(sock, priority) < 0) { - ERROR_FAILED(err, "set_priority", errno); - return FALSE; - } - - if (sec_level && !set_sec_level(sock, BT_IO_L2CAP, sec_level, err)) - return FALSE; - - return TRUE; -} - -static int rfcomm_bind(int sock, - const bdaddr_t *src, uint8_t channel, GError **err) -{ - struct sockaddr_rc addr; - - memset(&addr, 0, sizeof(addr)); - addr.rc_family = AF_BLUETOOTH; - bacpy(&addr.rc_bdaddr, src); - addr.rc_channel = channel; - - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - int error = -errno; - ERROR_FAILED(err, "rfcomm_bind", errno); - return error; - } - - return 0; -} - -static int rfcomm_connect(int sock, const bdaddr_t *dst, uint8_t channel) -{ - int err; - struct sockaddr_rc addr; - - memset(&addr, 0, sizeof(addr)); - addr.rc_family = AF_BLUETOOTH; - bacpy(&addr.rc_bdaddr, dst); - addr.rc_channel = channel; - - err = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) - return -errno; - - return 0; -} - -static gboolean rfcomm_set(int sock, int sec_level, int master, GError **err) -{ - if (sec_level && !set_sec_level(sock, BT_IO_RFCOMM, sec_level, err)) - return FALSE; - - if (master >= 0 && rfcomm_set_master(sock, master) < 0) { - ERROR_FAILED(err, "rfcomm_set_master", errno); - return FALSE; - } - - return TRUE; -} - -static int sco_bind(int sock, const bdaddr_t *src, GError **err) -{ - struct sockaddr_sco addr; - - memset(&addr, 0, sizeof(addr)); - addr.sco_family = AF_BLUETOOTH; - bacpy(&addr.sco_bdaddr, src); - - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - int error = -errno; - ERROR_FAILED(err, "sco_bind", errno); - return error; - } - - return 0; -} - -static int sco_connect(int sock, const bdaddr_t *dst) -{ - struct sockaddr_sco addr; - int err; - - memset(&addr, 0, sizeof(addr)); - addr.sco_family = AF_BLUETOOTH; - bacpy(&addr.sco_bdaddr, dst); - - err = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) - return -errno; - - return 0; -} - -static gboolean sco_set(int sock, uint16_t mtu, GError **err) -{ - struct sco_options sco_opt; - socklen_t len; - - if (!mtu) - return TRUE; - - len = sizeof(sco_opt); - memset(&sco_opt, 0, len); - if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) { - ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno); - return FALSE; - } - - sco_opt.mtu = mtu; - if (setsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, - sizeof(sco_opt)) < 0) { - ERROR_FAILED(err, "setsockopt(SCO_OPTIONS)", errno); - return FALSE; - } - - return TRUE; -} - -static gboolean parse_set_opts(struct set_opts *opts, GError **err, - BtIOOption opt1, va_list args) -{ - BtIOOption opt = opt1; - const char *str; - - memset(opts, 0, sizeof(*opts)); - - /* Set defaults */ - opts->defer = DEFAULT_DEFER_TIMEOUT; - opts->master = -1; - opts->mode = L2CAP_MODE_BASIC; - opts->flushable = -1; - opts->priority = 0; - - while (opt != BT_IO_OPT_INVALID) { - switch (opt) { - case BT_IO_OPT_SOURCE: - str = va_arg(args, const char *); - str2ba(str, &opts->src); - break; - case BT_IO_OPT_SOURCE_BDADDR: - bacpy(&opts->src, va_arg(args, const bdaddr_t *)); - break; - case BT_IO_OPT_DEST: - str2ba(va_arg(args, const char *), &opts->dst); - break; - case BT_IO_OPT_DEST_BDADDR: - bacpy(&opts->dst, va_arg(args, const bdaddr_t *)); - break; - case BT_IO_OPT_DEFER_TIMEOUT: - opts->defer = va_arg(args, int); - break; - case BT_IO_OPT_SEC_LEVEL: - opts->sec_level = va_arg(args, int); - break; - case BT_IO_OPT_CHANNEL: - opts->channel = va_arg(args, int); - break; - case BT_IO_OPT_PSM: - opts->psm = va_arg(args, int); - break; - case BT_IO_OPT_CID: - opts->cid = va_arg(args, int); - break; - case BT_IO_OPT_MTU: - opts->mtu = va_arg(args, int); - opts->imtu = opts->mtu; - opts->omtu = opts->mtu; - break; - case BT_IO_OPT_OMTU: - opts->omtu = va_arg(args, int); - if (!opts->mtu) - opts->mtu = opts->omtu; - break; - case BT_IO_OPT_IMTU: - opts->imtu = va_arg(args, int); - if (!opts->mtu) - opts->mtu = opts->imtu; - break; - case BT_IO_OPT_MASTER: - opts->master = va_arg(args, gboolean); - break; - case BT_IO_OPT_MODE: - opts->mode = va_arg(args, int); - break; - case BT_IO_OPT_FLUSHABLE: - opts->flushable = va_arg(args, gboolean); - break; - case BT_IO_OPT_PRIORITY: - opts->priority = va_arg(args, int); - break; - default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown option %d", opt); - return FALSE; - } - - opt = va_arg(args, int); - } - - return TRUE; -} - -static gboolean get_peers(int sock, struct sockaddr *src, struct sockaddr *dst, - socklen_t len, GError **err) -{ - socklen_t olen; - - memset(src, 0, len); - olen = len; - if (getsockname(sock, src, &olen) < 0) { - ERROR_FAILED(err, "getsockname", errno); - return FALSE; - } - - memset(dst, 0, len); - olen = len; - if (getpeername(sock, dst, &olen) < 0) { - ERROR_FAILED(err, "getpeername", errno); - return FALSE; - } - - return TRUE; -} - -static int l2cap_get_info(int sock, uint16_t *handle, uint8_t *dev_class) -{ - struct l2cap_conninfo info; - socklen_t len; - - len = sizeof(info); - if (getsockopt(sock, SOL_L2CAP, L2CAP_CONNINFO, &info, &len) < 0) - return -errno; - - if (handle) - *handle = info.hci_handle; - - if (dev_class) - memcpy(dev_class, info.dev_class, 3); - - return 0; -} - -static int l2cap_get_flushable(int sock, gboolean *flushable) -{ - int f; - socklen_t len; - - f = 0; - len = sizeof(f); - if (getsockopt(sock, SOL_BLUETOOTH, BT_FLUSHABLE, &f, &len) < 0) - return -errno; - - if (f) - *flushable = TRUE; - else - *flushable = FALSE; - - return 0; -} - -static int get_priority(int sock, uint32_t *prio) -{ - socklen_t len; - - len = sizeof(*prio); - if (getsockopt(sock, SOL_SOCKET, SO_PRIORITY, prio, &len) < 0) - return -errno; - - return 0; -} - -static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1, - va_list args) -{ - BtIOOption opt = opt1; - struct sockaddr_l2 src, dst; - struct l2cap_options l2o; - int flags; - uint8_t dev_class[3]; - uint16_t handle; - socklen_t len; - gboolean flushable = FALSE; - uint32_t priority; - - len = sizeof(l2o); - memset(&l2o, 0, len); - if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) { - ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno); - return FALSE; - } - - if (!get_peers(sock, (struct sockaddr *) &src, - (struct sockaddr *) &dst, sizeof(src), err)) - return FALSE; - - while (opt != BT_IO_OPT_INVALID) { - switch (opt) { - case BT_IO_OPT_SOURCE: - ba2str(&src.l2_bdaddr, va_arg(args, char *)); - break; - case BT_IO_OPT_SOURCE_BDADDR: - bacpy(va_arg(args, bdaddr_t *), &src.l2_bdaddr); - break; - case BT_IO_OPT_DEST: - ba2str(&dst.l2_bdaddr, va_arg(args, char *)); - break; - case BT_IO_OPT_DEST_BDADDR: - bacpy(va_arg(args, bdaddr_t *), &dst.l2_bdaddr); - break; - case BT_IO_OPT_DEFER_TIMEOUT: - len = sizeof(int); - if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, - va_arg(args, int *), &len) < 0) { - ERROR_FAILED(err, "getsockopt(DEFER_SETUP)", - errno); - return FALSE; - } - break; - case BT_IO_OPT_SEC_LEVEL: - if (!get_sec_level(sock, BT_IO_L2CAP, - va_arg(args, int *), err)) - return FALSE; - break; - case BT_IO_OPT_KEY_SIZE: - if (!get_key_size(sock, va_arg(args, int *), err)) - return FALSE; - break; - case BT_IO_OPT_PSM: - *(va_arg(args, uint16_t *)) = src.l2_psm ? - btohs(src.l2_psm) : btohs(dst.l2_psm); - break; - case BT_IO_OPT_CID: - *(va_arg(args, uint16_t *)) = src.l2_cid ? - btohs(src.l2_cid) : btohs(dst.l2_cid); - break; - case BT_IO_OPT_OMTU: - *(va_arg(args, uint16_t *)) = l2o.omtu; - break; - case BT_IO_OPT_IMTU: - *(va_arg(args, uint16_t *)) = l2o.imtu; - break; - case BT_IO_OPT_MASTER: - len = sizeof(flags); - if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, - &len) < 0) { - ERROR_FAILED(err, "getsockopt(L2CAP_LM)", - errno); - return FALSE; - } - *(va_arg(args, gboolean *)) = - (flags & L2CAP_LM_MASTER) ? TRUE : FALSE; - break; - case BT_IO_OPT_HANDLE: - if (l2cap_get_info(sock, &handle, dev_class) < 0) { - ERROR_FAILED(err, "L2CAP_CONNINFO", errno); - return FALSE; - } - *(va_arg(args, uint16_t *)) = handle; - break; - case BT_IO_OPT_CLASS: - if (l2cap_get_info(sock, &handle, dev_class) < 0) { - ERROR_FAILED(err, "L2CAP_CONNINFO", errno); - return FALSE; - } - memcpy(va_arg(args, uint8_t *), dev_class, 3); - break; - case BT_IO_OPT_MODE: - *(va_arg(args, uint8_t *)) = l2o.mode; - break; - case BT_IO_OPT_FLUSHABLE: - if (l2cap_get_flushable(sock, &flushable) < 0) { - ERROR_FAILED(err, "get_flushable", errno); - return FALSE; - } - *(va_arg(args, gboolean *)) = flushable; - break; - case BT_IO_OPT_PRIORITY: - if (get_priority(sock, &priority) < 0) { - ERROR_FAILED(err, "get_priority", errno); - return FALSE; - } - *(va_arg(args, uint32_t *)) = priority; - break; - default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown option %d", opt); - return FALSE; - } - - opt = va_arg(args, int); - } - - return TRUE; -} - -static int rfcomm_get_info(int sock, uint16_t *handle, uint8_t *dev_class) -{ - struct rfcomm_conninfo info; - socklen_t len; - - len = sizeof(info); - if (getsockopt(sock, SOL_RFCOMM, RFCOMM_CONNINFO, &info, &len) < 0) - return -errno; - - if (handle) - *handle = info.hci_handle; - - if (dev_class) - memcpy(dev_class, info.dev_class, 3); - - return 0; -} - -static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1, - va_list args) -{ - BtIOOption opt = opt1; - struct sockaddr_rc src, dst; - int flags; - socklen_t len; - uint8_t dev_class[3]; - uint16_t handle; - - if (!get_peers(sock, (struct sockaddr *) &src, - (struct sockaddr *) &dst, sizeof(src), err)) - return FALSE; - - while (opt != BT_IO_OPT_INVALID) { - switch (opt) { - case BT_IO_OPT_SOURCE: - ba2str(&src.rc_bdaddr, va_arg(args, char *)); - break; - case BT_IO_OPT_SOURCE_BDADDR: - bacpy(va_arg(args, bdaddr_t *), &src.rc_bdaddr); - break; - case BT_IO_OPT_DEST: - ba2str(&dst.rc_bdaddr, va_arg(args, char *)); - break; - case BT_IO_OPT_DEST_BDADDR: - bacpy(va_arg(args, bdaddr_t *), &dst.rc_bdaddr); - break; - case BT_IO_OPT_DEFER_TIMEOUT: - len = sizeof(int); - if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, - va_arg(args, int *), &len) < 0) { - ERROR_FAILED(err, "getsockopt(DEFER_SETUP)", - errno); - return FALSE; - } - break; - case BT_IO_OPT_SEC_LEVEL: - if (!get_sec_level(sock, BT_IO_RFCOMM, - va_arg(args, int *), err)) - return FALSE; - break; - case BT_IO_OPT_CHANNEL: - *(va_arg(args, uint8_t *)) = src.rc_channel ? - src.rc_channel : dst.rc_channel; - break; - case BT_IO_OPT_SOURCE_CHANNEL: - *(va_arg(args, uint8_t *)) = src.rc_channel; - break; - case BT_IO_OPT_DEST_CHANNEL: - *(va_arg(args, uint8_t *)) = dst.rc_channel; - break; - case BT_IO_OPT_MASTER: - len = sizeof(flags); - if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, - &len) < 0) { - ERROR_FAILED(err, "getsockopt(RFCOMM_LM)", - errno); - return FALSE; - } - *(va_arg(args, gboolean *)) = - (flags & RFCOMM_LM_MASTER) ? TRUE : FALSE; - break; - case BT_IO_OPT_HANDLE: - if (rfcomm_get_info(sock, &handle, dev_class) < 0) { - ERROR_FAILED(err, "RFCOMM_CONNINFO", errno); - return FALSE; - } - *(va_arg(args, uint16_t *)) = handle; - break; - case BT_IO_OPT_CLASS: - if (rfcomm_get_info(sock, &handle, dev_class) < 0) { - ERROR_FAILED(err, "RFCOMM_CONNINFO", errno); - return FALSE; - } - memcpy(va_arg(args, uint8_t *), dev_class, 3); - break; - default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown option %d", opt); - return FALSE; - } - - opt = va_arg(args, int); - } - - return TRUE; -} - -static int sco_get_info(int sock, uint16_t *handle, uint8_t *dev_class) -{ - struct sco_conninfo info; - socklen_t len; - - len = sizeof(info); - if (getsockopt(sock, SOL_SCO, SCO_CONNINFO, &info, &len) < 0) - return -errno; - - if (handle) - *handle = info.hci_handle; - - if (dev_class) - memcpy(dev_class, info.dev_class, 3); - - return 0; -} - -static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args) -{ - BtIOOption opt = opt1; - struct sockaddr_sco src, dst; - struct sco_options sco_opt; - socklen_t len; - uint8_t dev_class[3]; - uint16_t handle; - - len = sizeof(sco_opt); - memset(&sco_opt, 0, len); - if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) { - ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno); - return FALSE; - } - - if (!get_peers(sock, (struct sockaddr *) &src, - (struct sockaddr *) &dst, sizeof(src), err)) - return FALSE; - - while (opt != BT_IO_OPT_INVALID) { - switch (opt) { - case BT_IO_OPT_SOURCE: - ba2str(&src.sco_bdaddr, va_arg(args, char *)); - break; - case BT_IO_OPT_SOURCE_BDADDR: - bacpy(va_arg(args, bdaddr_t *), &src.sco_bdaddr); - break; - case BT_IO_OPT_DEST: - ba2str(&dst.sco_bdaddr, va_arg(args, char *)); - break; - case BT_IO_OPT_DEST_BDADDR: - bacpy(va_arg(args, bdaddr_t *), &dst.sco_bdaddr); - break; - case BT_IO_OPT_MTU: - case BT_IO_OPT_IMTU: - case BT_IO_OPT_OMTU: - *(va_arg(args, uint16_t *)) = sco_opt.mtu; - break; - case BT_IO_OPT_HANDLE: - if (sco_get_info(sock, &handle, dev_class) < 0) { - ERROR_FAILED(err, "SCO_CONNINFO", errno); - return FALSE; - } - *(va_arg(args, uint16_t *)) = handle; - break; - case BT_IO_OPT_CLASS: - if (sco_get_info(sock, &handle, dev_class) < 0) { - ERROR_FAILED(err, "SCO_CONNINFO", errno); - return FALSE; - } - memcpy(va_arg(args, uint8_t *), dev_class, 3); - break; - default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown option %d", opt); - return FALSE; - } - - opt = va_arg(args, int); - } - - return TRUE; -} - -static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, va_list args) -{ - int sock; - - sock = g_io_channel_unix_get_fd(io); - - switch (type) { - case BT_IO_L2RAW: - case BT_IO_L2CAP: - case BT_IO_L2ERTM: - return l2cap_get(sock, err, opt1, args); - case BT_IO_RFCOMM: - return rfcomm_get(sock, err, opt1, args); - case BT_IO_SCO: - return sco_get(sock, err, opt1, args); - } - - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); - return FALSE; -} - -gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data, - GDestroyNotify destroy, GError **err) -{ - int sock; - char c; - struct pollfd pfd; - - sock = g_io_channel_unix_get_fd(io); - - memset(&pfd, 0, sizeof(pfd)); - pfd.fd = sock; - pfd.events = POLLOUT; - - if (poll(&pfd, 1, 0) < 0) { - ERROR_FAILED(err, "poll", errno); - return FALSE; - } - - if (!(pfd.revents & POLLOUT)) { - if (read(sock, &c, 1) < 0) { - ERROR_FAILED(err, "read", errno); - return FALSE; - } - } - - accept_add(io, connect, user_data, destroy); - - return TRUE; -} - -gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...) -{ - va_list args; - gboolean ret; - struct set_opts opts; - int sock; - - va_start(args, opt1); - ret = parse_set_opts(&opts, err, opt1, args); - va_end(args); - - if (!ret) - return ret; - - sock = g_io_channel_unix_get_fd(io); - - switch (type) { - case BT_IO_L2RAW: - case BT_IO_L2CAP: - case BT_IO_L2ERTM: - return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu, - opts.mode, opts.master, opts.flushable, - opts.priority, err); - case BT_IO_RFCOMM: - return rfcomm_set(sock, opts.sec_level, opts.master, err); - case BT_IO_SCO: - return sco_set(sock, opts.mtu, err); - } - - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); - return FALSE; -} - -gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...) -{ - va_list args; - gboolean ret; - - va_start(args, opt1); - ret = get_valist(io, type, err, opt1, args); - va_end(args); - - return ret; -} - -static GIOChannel *create_io(BtIOType type, gboolean server, - struct set_opts *opts, GError **err) -{ - int sock; - GIOChannel *io; - - switch (type) { - case BT_IO_L2RAW: - sock = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP); - if (sock < 0) { - ERROR_FAILED(err, "socket(RAW, L2CAP)", errno); - return NULL; - } - if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0, - opts->cid, err) < 0) - goto failed; - if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, -1, 0, err)) - goto failed; - break; - case BT_IO_L2CAP: - sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - if (sock < 0) { - ERROR_FAILED(err, "socket(SEQPACKET, L2CAP)", errno); - return NULL; - } - if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0, - opts->cid, err) < 0) - goto failed; - if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu, - opts->mode, opts->master, opts->flushable, - opts->priority, err)) - goto failed; - break; - case BT_IO_L2ERTM: - sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP); - if (sock < 0) { - ERROR_FAILED(err, "socket(STREAM, L2CAP)", errno); - return NULL; - } - if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0, - opts->cid, err) < 0) - goto failed; - if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu, - opts->mode, opts->master, opts->flushable, - opts->priority, err)) - goto failed; - break; - case BT_IO_RFCOMM: - sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sock < 0) { - ERROR_FAILED(err, "socket(STREAM, RFCOMM)", errno); - return NULL; - } - if (rfcomm_bind(sock, &opts->src, - server ? opts->channel : 0, err) < 0) - goto failed; - if (!rfcomm_set(sock, opts->sec_level, opts->master, err)) - goto failed; - break; - case BT_IO_SCO: - sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); - if (sock < 0) { - ERROR_FAILED(err, "socket(SEQPACKET, SCO)", errno); - return NULL; - } - if (sco_bind(sock, &opts->src, err) < 0) - goto failed; - if (!sco_set(sock, opts->mtu, err)) - goto failed; - break; - default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); - return NULL; - } - - io = g_io_channel_unix_new(sock); - - g_io_channel_set_close_on_unref(io, TRUE); - g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL); - - return io; - -failed: - close(sock); - - return NULL; -} - -GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect, - gpointer user_data, GDestroyNotify destroy, - GError **gerr, BtIOOption opt1, ...) -{ - GIOChannel *io; - va_list args; - struct set_opts opts; - int err, sock; - gboolean ret; - - va_start(args, opt1); - ret = parse_set_opts(&opts, gerr, opt1, args); - va_end(args); - - if (ret == FALSE) - return NULL; - - io = create_io(type, FALSE, &opts, gerr); - if (io == NULL) - return NULL; - - sock = g_io_channel_unix_get_fd(io); - - switch (type) { - case BT_IO_L2RAW: - err = l2cap_connect(sock, &opts.dst, 0, opts.cid); - break; - case BT_IO_L2CAP: - case BT_IO_L2ERTM: - err = l2cap_connect(sock, &opts.dst, opts.psm, opts.cid); - break; - case BT_IO_RFCOMM: - err = rfcomm_connect(sock, &opts.dst, opts.channel); - break; - case BT_IO_SCO: - err = sco_connect(sock, &opts.dst); - break; - default: - g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); - return NULL; - } - - if (err < 0) { - g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED, - "connect: %s (%d)", strerror(-err), -err); - g_io_channel_unref(io); - return NULL; - } - - connect_add(io, connect, user_data, destroy); - - return io; -} - -GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect, - BtIOConfirm confirm, gpointer user_data, - GDestroyNotify destroy, GError **err, - BtIOOption opt1, ...) -{ - GIOChannel *io; - va_list args; - struct set_opts opts; - int sock; - gboolean ret; - - if (type == BT_IO_L2RAW) { - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Server L2CAP RAW sockets not supported"); - return NULL; - } - - va_start(args, opt1); - ret = parse_set_opts(&opts, err, opt1, args); - va_end(args); - - if (ret == FALSE) - return NULL; - - io = create_io(type, TRUE, &opts, err); - if (io == NULL) - return NULL; - - sock = g_io_channel_unix_get_fd(io); - - if (confirm) - setsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, &opts.defer, - sizeof(opts.defer)); - - if (listen(sock, 5) < 0) { - ERROR_FAILED(err, "listen", errno); - g_io_channel_unref(io); - return NULL; - } - - server_add(io, connect, confirm, user_data, destroy); - - return io; -} - -GQuark bt_io_error_quark(void) -{ - return g_quark_from_static_string("bt-io-error-quark"); -} diff --git a/btio/btio.h b/btio/btio.h deleted file mode 100644 index 429e8c0e9301..000000000000 --- a/btio/btio.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2009-2010 Marcel Holtmann - * Copyright (C) 2009-2010 Nokia Corporation - * - * - * 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 - * - */ -#ifndef BT_IO_H -#define BT_IO_H - -#include - -typedef enum { - BT_IO_ERROR_DISCONNECTED, - BT_IO_ERROR_CONNECT_FAILED, - BT_IO_ERROR_FAILED, - BT_IO_ERROR_INVALID_ARGS, -} BtIOError; - -#define BT_IO_ERROR bt_io_error_quark() - -GQuark bt_io_error_quark(void); - -typedef enum { - BT_IO_L2RAW, - BT_IO_L2CAP, - BT_IO_L2ERTM, - BT_IO_RFCOMM, - BT_IO_SCO, -} BtIOType; - -typedef enum { - BT_IO_OPT_INVALID = 0, - BT_IO_OPT_SOURCE, - BT_IO_OPT_SOURCE_BDADDR, - BT_IO_OPT_DEST, - BT_IO_OPT_DEST_BDADDR, - BT_IO_OPT_DEFER_TIMEOUT, - BT_IO_OPT_SEC_LEVEL, - BT_IO_OPT_KEY_SIZE, - BT_IO_OPT_CHANNEL, - BT_IO_OPT_SOURCE_CHANNEL, - BT_IO_OPT_DEST_CHANNEL, - BT_IO_OPT_PSM, - BT_IO_OPT_CID, - BT_IO_OPT_MTU, - BT_IO_OPT_OMTU, - BT_IO_OPT_IMTU, - BT_IO_OPT_MASTER, - BT_IO_OPT_HANDLE, - BT_IO_OPT_CLASS, - BT_IO_OPT_MODE, - BT_IO_OPT_FLUSHABLE, - BT_IO_OPT_PRIORITY, -} BtIOOption; - -typedef enum { - BT_IO_SEC_SDP = 0, - BT_IO_SEC_LOW, - BT_IO_SEC_MEDIUM, - BT_IO_SEC_HIGH, -} BtIOSecLevel; - -typedef enum { - BT_IO_MODE_BASIC = 0, - BT_IO_MODE_RETRANS, - BT_IO_MODE_FLOWCTL, - BT_IO_MODE_ERTM, - BT_IO_MODE_STREAMING -} BtIOMode; - -typedef void (*BtIOConfirm)(GIOChannel *io, gpointer user_data); - -typedef void (*BtIOConnect)(GIOChannel *io, GError *err, gpointer user_data); - -gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data, - GDestroyNotify destroy, GError **err); - -gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...); - -gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...); - -GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect, - gpointer user_data, GDestroyNotify destroy, - GError **err, BtIOOption opt1, ...); - -GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect, - BtIOConfirm confirm, gpointer user_data, - GDestroyNotify destroy, GError **err, - BtIOOption opt1, ...); - -#endif diff --git a/configure.ac b/configure.ac index 19adf3698c75..8eb8dd048fdb 100644 --- a/configure.ac +++ b/configure.ac @@ -247,7 +247,6 @@ if (test "${enable_bluez4}" = "yes"); then AC_SUBST(BLUEZ_LIBS) fi -AM_CONDITIONAL(BLUEZ4, test "${enable_bluetooth}" != "no" && test "${enable_bluez4}" = "yes") AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no") AC_ARG_ENABLE(upower, AS_HELP_STRING([--disable-upower], diff --git a/dundee/bluez4.c b/dundee/bluez4.c deleted file mode 100644 index c85f03e54a9f..000000000000 --- a/dundee/bluez4.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * oFono - Open Source Telephony - * - * Copyright (C) 2008-2012 Intel Corporation. All rights reserved. - * Copyright (C) 2012 BMW Car IT GmbH. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 - -#include - -#include "plugins/bluez4.h" - -#include "dundee.h" - -static GHashTable *bluetooth_hash; - -struct bluetooth_device { - struct dundee_device *device; - - char *path; - char *address; - char *name; - - int fd; - - DBusPendingCall *call; -}; - -static void bt_disconnect(struct dundee_device *device, - dundee_device_disconnect_cb_t cb, void *data) -{ - struct bluetooth_device *bt = dundee_device_get_data(device); - - DBG("%p", bt); - - shutdown(bt->fd, SHUT_RDWR); - - CALLBACK_WITH_SUCCESS(cb, data); -} - -static void bt_connect_reply(DBusPendingCall *call, gpointer user_data) -{ - struct cb_data *cbd = user_data; - dundee_device_connect_cb_t cb = cbd->cb; - struct bluetooth_device *bt = cbd->user; - DBusMessage *reply; - DBusError derr; - int fd; - - DBG("%p", bt); - - reply = dbus_pending_call_steal_reply(call); - - bt->call = NULL; - - dbus_error_init(&derr); - if (dbus_set_error_from_message(&derr, reply)) { - DBG("Connection to bt serial returned with error: %s, %s", - derr.name, derr.message); - - dbus_error_free(&derr); - - CALLBACK_WITH_FAILURE(cb, -1, cbd->data); - goto done; - } - - dbus_message_get_args(reply, NULL, DBUS_TYPE_UNIX_FD, &fd, - DBUS_TYPE_INVALID); - - DBG("%p fd %d", bt, fd); - - if (fd < 0) { - CALLBACK_WITH_FAILURE(cb, -1, cbd->data); - goto done; - } - - bt->fd = fd; - - CALLBACK_WITH_SUCCESS(cb, fd, cbd->data); - -done: - dbus_message_unref(reply); - g_free(cbd); -} - -static void bt_connect(struct dundee_device *device, - dundee_device_connect_cb_t cb, void *data) -{ - struct bluetooth_device *bt = dundee_device_get_data(device); - struct cb_data *cbd = cb_data_new(cb, data); - char *profile = "dun"; - int status; - - DBG("%p", bt); - - cbd->user = bt; - - status = bluetooth_send_with_reply(bt->path, - BLUEZ_SERIAL_INTERFACE, "ConnectFD", - &bt->call, bt_connect_reply, - cbd, NULL, DBUS_TIMEOUT, - DBUS_TYPE_STRING, &profile, - DBUS_TYPE_INVALID); - if (status == 0) - return; - - CALLBACK_WITH_FAILURE(cb, -1, cbd->data); - g_free(cbd); -} - -struct dundee_device_driver bluetooth_driver = { - .name = "bluetooth", - .connect = bt_connect, - .disconnect = bt_disconnect, -}; - -static int bt_probe(const char *path, const char *dev_addr, - const char *adapter_addr, const char *alias) -{ - struct bluetooth_device *bt; - struct dundee_device *device; - char buf[256]; - - DBG(""); - - /* We already have this device in our hash, ignore */ - if (g_hash_table_lookup(bluetooth_hash, path) != NULL) - return -EALREADY; - - ofono_info("Using device: %s, devaddr: %s, adapter: %s", - path, dev_addr, adapter_addr); - - strcpy(buf, "dun/"); - bluetooth_create_path(dev_addr, adapter_addr, buf + 4, sizeof(buf) - 4); - - bt = g_try_new0(struct bluetooth_device, 1); - if (bt == NULL) - return -ENOMEM; - - DBG("%p", bt); - - device = dundee_device_create(&bluetooth_driver); - if (device == NULL) - goto free; - - dundee_device_set_data(device, bt); - - bt->path = g_strdup(path); - if (bt->path == NULL) - goto free; - - bt->address = g_strdup(dev_addr); - if (bt->address == NULL) - goto free; - - bt->name = g_strdup(alias); - if (bt->name == NULL) - goto free; - - dundee_device_set_name(device, bt->name); - - if (dundee_device_register(device) < 0) { - g_free(device); - goto free; - } - - bt->device = device; - g_hash_table_insert(bluetooth_hash, g_strdup(path), bt); - - return 0; - -free: - g_free(bt->path); - g_free(bt->address); - g_free(bt->name); - g_free(bt); - - return -ENOMEM; -} - -static void destroy_device(gpointer user) -{ - struct bluetooth_device *bt = user; - - DBG("%p", bt); - - if (bt->call != NULL) - dbus_pending_call_cancel(bt->call); - - g_free(bt->path); - g_free(bt->address); - - g_free(bt); -} - -static gboolean bt_remove_device(gpointer key, gpointer value, - gpointer user_data) -{ - struct bluetooth_device *bt = value; - const char *path = key; - const char *prefix = user_data; - - DBG("%p", bt); - - if (prefix && g_str_has_prefix(path, prefix) == FALSE) - return FALSE; - - dundee_device_unregister(bt->device); - - return TRUE; -} - -static void bt_remove(const char *prefix) -{ - DBG("%s", prefix); - - if (bluetooth_hash == NULL) - return; - - g_hash_table_foreach_remove(bluetooth_hash, bt_remove_device, - (gpointer) prefix); -} - -static void bt_set_alias(const char *path, const char *alias) -{ - struct bluetooth_device *bt; - - DBG(""); - - if (path == NULL || alias == NULL) - return; - - bt = g_hash_table_lookup(bluetooth_hash, path); - if (bt == NULL) - return; - - g_free(bt->name); - bt->name = g_strdup(alias); - - dundee_device_set_name(bt->device, bt->name); -} - -static struct bluetooth_profile dun_profile = { - .name = "dun_dt", - .probe = bt_probe, - .remove = bt_remove, - .set_alias = bt_set_alias, -}; - -int __dundee_bluetooth_init(void) -{ - int err; - - DBG(""); - - err = bluetooth_register_uuid(DUN_GW_UUID, &dun_profile); - if (err < 0) - return err; - - bluetooth_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, destroy_device); - - return 0; -} - -void __dundee_bluetooth_cleanup(void) -{ - DBG(""); - - bluetooth_unregister_uuid(DUN_GW_UUID); - g_hash_table_destroy(bluetooth_hash); -} diff --git a/plugins/bluez4.c b/plugins/bluez4.c deleted file mode 100644 index 0558da3171db..000000000000 --- a/plugins/bluez4.c +++ /dev/null @@ -1,988 +0,0 @@ -/* - * - * oFono - Open Source Telephony - * - * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. - * Copyright (C) 2010 ProFUSION embedded systems - * Copyright (C) 2010 Gustavo F. Padovan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 -#include - -#define OFONO_API_SUBJECT_TO_CHANGE -#include -#include - -#include -#include "bluez4.h" - -static DBusConnection *connection; -static GHashTable *uuid_hash = NULL; -static GHashTable *adapter_address_hash = NULL; -static gint bluetooth_refcount; -static GSList *server_list = NULL; -static const char *adapter_any_name = "any"; -static char *adapter_any_path; - -#define TIMEOUT 60 /* Timeout for user response (seconds) */ - -struct server { - guint8 channel; - char *sdp_record; - guint32 handle; - GIOChannel *io; - ConnectFunc connect_cb; - gpointer user_data; -}; - -struct cb_data { - struct server *server; - char *path; - guint source; - GIOChannel *io; -}; - -void bluetooth_create_path(const char *dev_addr, const char *adapter_addr, - char *buf, int size) -{ - int i, j; - - for (i = 0, j = 0; adapter_addr[j] && i < size - 1; j++) - if (adapter_addr[j] >= '0' && adapter_addr[j] <= '9') - buf[i++] = adapter_addr[j]; - else if (adapter_addr[j] >= 'A' && adapter_addr[j] <= 'F') - buf[i++] = adapter_addr[j]; - - if (i < size - 1) - buf[i++] = '_'; - - for (j = 0; dev_addr[j] && i < size - 1; j++) - if (dev_addr[j] >= '0' && dev_addr[j] <= '9') - buf[i++] = dev_addr[j]; - else if (dev_addr[j] >= 'A' && dev_addr[j] <= 'F') - buf[i++] = dev_addr[j]; - - buf[i] = '\0'; -} - -int bluetooth_send_with_reply(const char *path, const char *interface, - const char *method, DBusPendingCall **call, - DBusPendingCallNotifyFunction cb, - void *user_data, DBusFreeFunction free_func, - int timeout, int type, ...) -{ - DBusMessage *msg; - DBusPendingCall *c; - va_list args; - int err; - - msg = dbus_message_new_method_call(BLUEZ_SERVICE, path, - interface, method); - if (msg == NULL) { - ofono_error("Unable to allocate new D-Bus %s message", method); - err = -ENOMEM; - goto fail; - } - - va_start(args, type); - - if (!dbus_message_append_args_valist(msg, type, args)) { - va_end(args); - err = -EIO; - goto fail; - } - - va_end(args); - - if (timeout > 0) - timeout *= 1000; - - if (!dbus_connection_send_with_reply(connection, msg, &c, timeout)) { - ofono_error("Sending %s failed", method); - err = -EIO; - goto fail; - } - - if (call != NULL) - *call = c; - - dbus_pending_call_set_notify(c, cb, user_data, free_func); - dbus_pending_call_unref(c); - - dbus_message_unref(msg); - - return 0; - -fail: - if (free_func && user_data) - free_func(user_data); - - if (msg) - dbus_message_unref(msg); - - return err; -} - -typedef void (*PropertyHandler)(DBusMessageIter *iter, gpointer user_data); - -struct property_handler { - const char *property; - PropertyHandler callback; - gpointer user_data; -}; - -static gint property_handler_compare(gconstpointer a, gconstpointer b) -{ - const struct property_handler *handler = a; - const char *property = b; - - return strcmp(handler->property, property); -} - -void bluetooth_parse_properties(DBusMessage *reply, const char *property, ...) -{ - va_list args; - GSList *prop_handlers = NULL; - DBusMessageIter array, dict; - - va_start(args, property); - - while (property != NULL) { - struct property_handler *handler = - g_new0(struct property_handler, 1); - - handler->property = property; - handler->callback = va_arg(args, PropertyHandler); - handler->user_data = va_arg(args, gpointer); - - property = va_arg(args, const char *); - - prop_handlers = g_slist_prepend(prop_handlers, handler); - } - - va_end(args); - - if (dbus_message_iter_init(reply, &array) == FALSE) - goto done; - - if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) - goto done; - - dbus_message_iter_recurse(&array, &dict); - - while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter entry, value; - const char *key; - GSList *l; - - dbus_message_iter_recurse(&dict, &entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) - goto done; - - dbus_message_iter_get_basic(&entry, &key); - - dbus_message_iter_next(&entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) - goto done; - - dbus_message_iter_recurse(&entry, &value); - - l = g_slist_find_custom(prop_handlers, key, - property_handler_compare); - - if (l) { - struct property_handler *handler = l->data; - - handler->callback(&value, handler->user_data); - } - - dbus_message_iter_next(&dict); - } - -done: - g_slist_free_full(prop_handlers, g_free); -} - -static void parse_uuids(DBusMessageIter *array, gpointer user_data) -{ - GSList **uuids = user_data; - DBusMessageIter value; - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return; - - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { - const char *uuid; - - dbus_message_iter_get_basic(&value, &uuid); - - *uuids = g_slist_prepend(*uuids, (char *) uuid); - - dbus_message_iter_next(&value); - } -} - -static void parse_string(DBusMessageIter *iter, gpointer user_data) -{ - char **str = user_data; - int arg_type = dbus_message_iter_get_arg_type(iter); - - if (arg_type != DBUS_TYPE_OBJECT_PATH && arg_type != DBUS_TYPE_STRING) - return; - - dbus_message_iter_get_basic(iter, str); -} - -static void bluetooth_probe(GSList *uuids, const char *path, - const char *device, const char *adapter, - const char *alias) -{ - for (; uuids; uuids = uuids->next) { - struct bluetooth_profile *driver; - const char *uuid = uuids->data; - int err; - - driver = g_hash_table_lookup(uuid_hash, uuid); - if (driver == NULL) - continue; - - err = driver->probe(path, device, adapter, alias); - if (err == 0 || err == -EALREADY) - continue; - - ofono_error("%s probe: %s (%d)", driver->name, strerror(-err), - -err); - } -} - -static void device_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - DBusMessage *reply; - const char *path = user_data; - const char *adapter = NULL; - const char *adapter_addr = NULL; - const char *device_addr = NULL; - const char *alias = NULL; - struct DBusError derr; - GSList *uuids = NULL; - - reply = dbus_pending_call_steal_reply(call); - - dbus_error_init(&derr); - - if (dbus_set_error_from_message(&derr, reply)) { - ofono_error("Device.GetProperties replied an error: %s, %s", - derr.name, derr.message); - dbus_error_free(&derr); - goto done; - } - - DBG(""); - - bluetooth_parse_properties(reply, "UUIDs", parse_uuids, &uuids, - "Adapter", parse_string, &adapter, - "Address", parse_string, &device_addr, - "Alias", parse_string, &alias, NULL); - - if (adapter) - adapter_addr = g_hash_table_lookup(adapter_address_hash, - adapter); - - if (!device_addr || !adapter_addr) - goto done; - - bluetooth_probe(uuids, path, device_addr, adapter_addr, alias); - -done: - g_slist_free(uuids); - dbus_message_unref(reply); -} - -static void parse_devices(DBusMessageIter *array, gpointer user_data) -{ - DBusMessageIter value; - GSList **device_list = user_data; - - DBG(""); - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return; - - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) - == DBUS_TYPE_OBJECT_PATH) { - const char *path; - - dbus_message_iter_get_basic(&value, &path); - - *device_list = g_slist_prepend(*device_list, (gpointer) path); - - dbus_message_iter_next(&value); - } -} - -static gboolean property_changed(DBusConnection *conn, DBusMessage *msg, - void *user_data) -{ - const char *property; - DBusMessageIter iter; - - dbus_message_iter_init(msg, &iter); - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - return FALSE; - - dbus_message_iter_get_basic(&iter, &property); - if (g_str_equal(property, "UUIDs") == TRUE) { - GSList *uuids = NULL; - const char *path = dbus_message_get_path(msg); - DBusMessageIter variant; - - if (!dbus_message_iter_next(&iter)) - return FALSE; - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - return FALSE; - - dbus_message_iter_recurse(&iter, &variant); - - parse_uuids(&variant, &uuids); - - /* We need the full set of properties to be able to create - * the modem properly, including Adapter and Alias, so - * refetch everything again - */ - if (uuids) - bluetooth_send_with_reply(path, BLUEZ_DEVICE_INTERFACE, - "GetProperties", NULL, - device_properties_cb, g_strdup(path), - g_free, -1, DBUS_TYPE_INVALID); - } else if (g_str_equal(property, "Alias") == TRUE) { - const char *path = dbus_message_get_path(msg); - struct bluetooth_profile *profile; - const char *alias = NULL; - DBusMessageIter variant; - GHashTableIter hash_iter; - gpointer key, value; - - if (!dbus_message_iter_next(&iter)) - return FALSE; - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - return FALSE; - - dbus_message_iter_recurse(&iter, &variant); - - parse_string(&variant, &alias); - - g_hash_table_iter_init(&hash_iter, uuid_hash); - while (g_hash_table_iter_next(&hash_iter, &key, &value)) { - profile = value; - if (profile->set_alias) - profile->set_alias(path, alias); - } - } - - return TRUE; -} - -static void adapter_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - const char *path = user_data; - DBusMessage *reply; - DBusError derr; - GSList *device_list = NULL; - GSList *l; - const char *addr; - - reply = dbus_pending_call_steal_reply(call); - - dbus_error_init(&derr); - - if (dbus_set_error_from_message(&derr, reply)) { - ofono_error("Adapter.GetProperties replied an error: %s, %s", - derr.name, derr.message); - dbus_error_free(&derr); - goto done; - } - - DBG(""); - - bluetooth_parse_properties(reply, - "Devices", parse_devices, &device_list, - "Address", parse_string, &addr, - NULL); - - DBG("Adapter Address: %s, Path: %s", addr, path); - g_hash_table_insert(adapter_address_hash, - g_strdup(path), g_strdup(addr)); - - for (l = device_list; l; l = l->next) { - const char *device = l->data; - - bluetooth_send_with_reply(device, BLUEZ_DEVICE_INTERFACE, - "GetProperties", NULL, - device_properties_cb, g_strdup(device), - g_free, -1, DBUS_TYPE_INVALID); - } - -done: - g_slist_free(device_list); - dbus_message_unref(reply); -} - -static void get_adapter_properties(const char *path, const char *handle, - gpointer user_data) -{ - bluetooth_send_with_reply(path, BLUEZ_ADAPTER_INTERFACE, - "GetProperties", NULL, adapter_properties_cb, - g_strdup(path), g_free, -1, DBUS_TYPE_INVALID); -} - -static void remove_record(struct server *server) -{ - DBusMessage *msg; - - if (server->handle == 0) - return; - - msg = dbus_message_new_method_call(BLUEZ_SERVICE, adapter_any_path, - BLUEZ_SERVICE_INTERFACE, - "RemoveRecord"); - if (msg == NULL) { - ofono_error("Unable to allocate D-Bus RemoveRecord message"); - return; - } - - dbus_message_append_args(msg, DBUS_TYPE_UINT32, &server->handle, - DBUS_TYPE_INVALID); - g_dbus_send_message(connection, msg); - - ofono_info("Unregistered handle for channel %d: 0x%x", - server->channel, server->handle); -} - -static void cb_data_destroy(gpointer data) -{ - struct cb_data *cb_data = data; - - if (cb_data->source != 0) - g_source_remove(cb_data->source); - - g_free(cb_data->path); - g_free(cb_data); -} - -static void cancel_authorization(struct cb_data *user_data) -{ - DBusMessage *msg; - - msg = dbus_message_new_method_call(BLUEZ_SERVICE, user_data->path, - BLUEZ_SERVICE_INTERFACE, - "CancelAuthorization"); - - if (msg == NULL) { - ofono_error("Unable to allocate D-Bus CancelAuthorization" - " message"); - return; - } - - g_dbus_send_message(connection, msg); -} - -static gboolean client_event(GIOChannel *chan, GIOCondition cond, gpointer data) -{ - struct cb_data *cb_data = data; - - cancel_authorization(cb_data); - cb_data->source = 0; - - return FALSE; -} - -static void auth_cb(DBusPendingCall *call, gpointer user_data) -{ - struct cb_data *cb_data = user_data; - struct server *server = cb_data->server; - DBusMessage *reply = dbus_pending_call_steal_reply(call); - DBusError derr; - GError *err = NULL; - - dbus_error_init(&derr); - - if (dbus_set_error_from_message(&derr, reply)) { - ofono_error("RequestAuthorization error: %s, %s", - derr.name, derr.message); - - if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY)) - cancel_authorization(cb_data); - - dbus_error_free(&derr); - } else { - ofono_info("RequestAuthorization succeeded"); - - if (!bt_io_accept(cb_data->io, server->connect_cb, - server->user_data, NULL, &err)) { - ofono_error("%s", err->message); - g_error_free(err); - } - } - - dbus_message_unref(reply); -} - -static void new_connection(GIOChannel *io, gpointer user_data) -{ - struct server *server = user_data; - struct cb_data *cbd; - const char *addr; - GError *err = NULL; - char laddress[18], raddress[18]; - guint8 channel; - GHashTableIter iter; - gpointer key, value; - const char *path; - - bt_io_get(io, BT_IO_RFCOMM, &err, BT_IO_OPT_SOURCE, laddress, - BT_IO_OPT_DEST, raddress, - BT_IO_OPT_CHANNEL, &channel, - BT_IO_OPT_INVALID); - if (err) { - ofono_error("%s", err->message); - g_error_free(err); - return; - } - - ofono_info("New connection for %s on channel %u from: %s,", laddress, - channel, raddress); - - path = NULL; - g_hash_table_iter_init(&iter, adapter_address_hash); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - if (g_str_equal(laddress, value) == TRUE) { - path = key; - break; - } - } - - if (path == NULL) - return; - - cbd = g_try_new0(struct cb_data, 1); - if (cbd == NULL) { - ofono_error("Unable to allocate client cb_data structure"); - return; - } - - cbd->path = g_strdup(path); - cbd->server = server; - cbd->io = io; - - addr = raddress; - - if (bluetooth_send_with_reply(path, BLUEZ_SERVICE_INTERFACE, - "RequestAuthorization", NULL, - auth_cb, cbd, cb_data_destroy, - TIMEOUT, DBUS_TYPE_STRING, &addr, - DBUS_TYPE_UINT32, &server->handle, - DBUS_TYPE_INVALID) < 0) { - ofono_error("Request Bluetooth authorization failed"); - return; - } - - ofono_info("RequestAuthorization(%s, 0x%x)", raddress, server->handle); - - cbd->source = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL, - client_event, cbd); -} - -static void remove_service_handle(gpointer data, gpointer user_data) -{ - struct server *server = data; - - server->handle = 0; -} - -static void add_record_cb(DBusPendingCall *call, gpointer user_data) -{ - struct server *server = user_data; - DBusMessage *reply = dbus_pending_call_steal_reply(call); - DBusError derr; - - dbus_error_init(&derr); - - if (dbus_set_error_from_message(&derr, reply)) { - ofono_error("Replied with an error: %s, %s", - derr.name, derr.message); - dbus_error_free(&derr); - goto done; - } - - dbus_message_get_args(reply, NULL, DBUS_TYPE_UINT32, &server->handle, - DBUS_TYPE_INVALID); - - ofono_info("Registered handle for channel %d: 0x%x", - server->channel, server->handle); - -done: - dbus_message_unref(reply); -} - -static void add_record(gpointer data, gpointer user_data) -{ - struct server *server = data; - - if (server->sdp_record == NULL) - return; - - bluetooth_send_with_reply(adapter_any_path, - BLUEZ_SERVICE_INTERFACE, "AddRecord", - NULL, add_record_cb, server, NULL, -1, - DBUS_TYPE_STRING, &server->sdp_record, - DBUS_TYPE_INVALID); -} - -static void find_adapter_cb(DBusPendingCall *call, gpointer user_data) -{ - DBusMessage *reply = dbus_pending_call_steal_reply(call); - DBusError derr; - const char *path; - - dbus_error_init(&derr); - - if (dbus_set_error_from_message(&derr, reply)) { - ofono_error("Replied with an error: %s, %s", - derr.name, derr.message); - dbus_error_free(&derr); - goto done; - } - - dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - adapter_any_path = g_strdup(path); - - g_slist_foreach(server_list, add_record, NULL); - -done: - dbus_message_unref(reply); -} - -static gboolean adapter_added(DBusConnection *conn, DBusMessage *message, - void *user_data) -{ - const char *path; - - dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - bluetooth_send_with_reply(path, BLUEZ_ADAPTER_INTERFACE, - "GetProperties", NULL, adapter_properties_cb, - g_strdup(path), g_free, -1, DBUS_TYPE_INVALID); - - return TRUE; -} - -static void bluetooth_remove(gpointer key, gpointer value, gpointer user_data) -{ - struct bluetooth_profile *profile = value; - - profile->remove(user_data); -} - -static gboolean adapter_removed(DBusConnection *conn, - DBusMessage *message, void *user_data) -{ - const char *path; - - if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == FALSE) - return FALSE; - - g_hash_table_foreach(uuid_hash, bluetooth_remove, (gpointer) path); - g_hash_table_remove(adapter_address_hash, path); - - return TRUE; -} - -static gboolean device_removed(DBusConnection *conn, - DBusMessage *message, void *user_data) -{ - const char *path; - - if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == FALSE) - return FALSE; - - g_hash_table_foreach(uuid_hash, bluetooth_remove, (gpointer) path); - - return TRUE; -} - -static void parse_adapters(DBusMessageIter *array, gpointer user_data) -{ - DBusMessageIter value; - - DBG(""); - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return; - - dbus_message_iter_recurse(array, &value); - - while (dbus_message_iter_get_arg_type(&value) - == DBUS_TYPE_OBJECT_PATH) { - const char *path; - - dbus_message_iter_get_basic(&value, &path); - - DBG("Calling GetProperties on %s", path); - - bluetooth_send_with_reply(path, BLUEZ_ADAPTER_INTERFACE, - "GetProperties", NULL, adapter_properties_cb, - g_strdup(path), g_free, -1, DBUS_TYPE_INVALID); - - dbus_message_iter_next(&value); - } -} - -static void manager_properties_cb(DBusPendingCall *call, gpointer user_data) -{ - DBusMessage *reply; - DBusError derr; - - reply = dbus_pending_call_steal_reply(call); - - dbus_error_init(&derr); - - if (dbus_set_error_from_message(&derr, reply)) { - ofono_error("Manager.GetProperties() replied an error: %s, %s", - derr.name, derr.message); - dbus_error_free(&derr); - goto done; - } - - DBG(""); - - bluetooth_parse_properties(reply, "Adapters", parse_adapters, NULL, - NULL); - -done: - dbus_message_unref(reply); -} - -static void bluetooth_connect(DBusConnection *conn, void *user_data) -{ - bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "GetProperties", - NULL, manager_properties_cb, NULL, NULL, -1, - DBUS_TYPE_INVALID); - - bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "FindAdapter", - NULL, find_adapter_cb, NULL, NULL, -1, - DBUS_TYPE_STRING, &adapter_any_name, - DBUS_TYPE_INVALID); -} - -static void bluetooth_disconnect(DBusConnection *conn, void *user_data) -{ - if (uuid_hash == NULL) - return; - - g_hash_table_foreach(uuid_hash, bluetooth_remove, NULL); - - g_slist_foreach(server_list, remove_service_handle, NULL); -} - -static guint bluetooth_watch; -static guint adapter_added_watch; -static guint adapter_removed_watch; -static guint device_removed_watch; -static guint property_watch; - -static void bluetooth_ref(void) -{ - if (bluetooth_refcount > 0) - goto increment; - - connection = ofono_dbus_get_connection(); - - bluetooth_watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE, - bluetooth_connect, - bluetooth_disconnect, NULL, NULL); - - adapter_added_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE, - NULL, BLUEZ_MANAGER_INTERFACE, - "AdapterAdded", - adapter_added, NULL, NULL); - - adapter_removed_watch = g_dbus_add_signal_watch(connection, - BLUEZ_SERVICE, NULL, - BLUEZ_MANAGER_INTERFACE, - "AdapterRemoved", - adapter_removed, NULL, NULL); - - device_removed_watch = g_dbus_add_signal_watch(connection, - BLUEZ_SERVICE, NULL, - BLUEZ_ADAPTER_INTERFACE, - "DeviceRemoved", - device_removed, NULL, NULL); - - property_watch = g_dbus_add_signal_watch(connection, - BLUEZ_SERVICE, NULL, - BLUEZ_DEVICE_INTERFACE, - "PropertyChanged", - property_changed, NULL, NULL); - - if (bluetooth_watch == 0 || adapter_added_watch == 0 || - adapter_removed_watch == 0 || property_watch == 0) { - goto remove; - } - - uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - - adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - -increment: - g_atomic_int_inc(&bluetooth_refcount); - - return; - -remove: - g_dbus_remove_watch(connection, bluetooth_watch); - g_dbus_remove_watch(connection, adapter_added_watch); - g_dbus_remove_watch(connection, adapter_removed_watch); - g_dbus_remove_watch(connection, property_watch); -} - -static void bluetooth_unref(void) -{ - if (g_atomic_int_dec_and_test(&bluetooth_refcount) == FALSE) - return; - - g_free(adapter_any_path); - adapter_any_path = NULL; - - g_dbus_remove_watch(connection, bluetooth_watch); - g_dbus_remove_watch(connection, adapter_added_watch); - g_dbus_remove_watch(connection, adapter_removed_watch); - g_dbus_remove_watch(connection, property_watch); - - g_hash_table_destroy(uuid_hash); - g_hash_table_destroy(adapter_address_hash); -} - -void bluetooth_get_properties() -{ - g_hash_table_foreach(adapter_address_hash, - (GHFunc) get_adapter_properties, NULL); -} - -int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile) -{ - bluetooth_ref(); - - g_hash_table_insert(uuid_hash, g_strdup(uuid), profile); - - g_hash_table_foreach(adapter_address_hash, - (GHFunc) get_adapter_properties, NULL); - - return 0; -} - -void bluetooth_unregister_uuid(const char *uuid) -{ - g_hash_table_remove(uuid_hash, uuid); - - bluetooth_unref(); -} - -struct server *bluetooth_register_server(guint8 channel, const char *sdp_record, - ConnectFunc cb, gpointer user_data) -{ - struct server *server; - GError *err = NULL; - - server = g_try_new0(struct server, 1); - if (!server) - return NULL; - - server->channel = channel; - - server->io = bt_io_listen(BT_IO_RFCOMM, NULL, new_connection, - server, NULL, &err, - BT_IO_OPT_CHANNEL, server->channel, - BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, - BT_IO_OPT_INVALID); - if (server->io == NULL) { - g_error_free(err); - g_free(server); - return NULL; - } - - bluetooth_ref(); - - if (sdp_record != NULL) - server->sdp_record = g_strdup(sdp_record); - - server->connect_cb = cb; - server->user_data = user_data; - - server_list = g_slist_prepend(server_list, server); - - if (adapter_any_path != NULL) - add_record(server, NULL); - - return server; -} - -void bluetooth_unregister_server(struct server *server) -{ - server_list = g_slist_remove(server_list, server); - - remove_record(server); - - if (server->io != NULL) { - g_io_channel_shutdown(server->io, TRUE, NULL); - g_io_channel_unref(server->io); - server->io = NULL; - } - - g_free(server->sdp_record); - g_free(server); - - bluetooth_unref(); -} - -OFONO_PLUGIN_DEFINE(bluez4, "Bluetooth Utils Plugins", VERSION, - OFONO_PLUGIN_PRIORITY_DEFAULT, NULL, NULL) diff --git a/plugins/bluez4.h b/plugins/bluez4.h deleted file mode 100644 index 3b60cbac299b..000000000000 --- a/plugins/bluez4.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * oFono - Open Source Telephony - * - * Copyright (C) 2010 Gustavo F. Padovan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 - -#define BLUEZ_SERVICE "org.bluez" -#define BLUEZ_MANAGER_INTERFACE BLUEZ_SERVICE ".Manager" -#define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter" -#define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device" -#define BLUEZ_SERVICE_INTERFACE BLUEZ_SERVICE ".Service" -#define BLUEZ_SERIAL_INTERFACE BLUEZ_SERVICE ".Serial" - -#define DBUS_TIMEOUT 60 - -#define DUN_GW_UUID "00001103-0000-1000-8000-00805f9b34fb" -#define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb" -#define HFP_HS_UUID "0000111e-0000-1000-8000-00805f9b34fb" -#define SAP_UUID "0000112d-0000-1000-8000-00805f9b34fb" - -struct bluetooth_profile { - const char *name; - int (*probe)(const char *device, const char *dev_addr, - const char *adapter_addr, const char *alias); - void (*remove)(const char *prefix); - void (*set_alias)(const char *device, const char *); -}; - -struct bluetooth_sap_driver { - const char *name; - int (*enable) (struct ofono_modem *modem, struct ofono_modem *sap_modem, - int bt_fd); - void (*pre_sim) (struct ofono_modem *modem); - void (*post_sim) (struct ofono_modem *modem); - void (*set_online) (struct ofono_modem *modem, ofono_bool_t online, - ofono_modem_online_cb_t cb, void *user_data); - void (*post_online) (struct ofono_modem *modem); - int (*disable) (struct ofono_modem *modem); -}; - -struct server; - -typedef void (*ConnectFunc)(GIOChannel *io, GError *err, gpointer user_data); - -void bluetooth_get_properties(); -int bluetooth_register_uuid(const char *uuid, - struct bluetooth_profile *profile); -void bluetooth_unregister_uuid(const char *uuid); - -struct server *bluetooth_register_server(guint8 channel, const char *sdp_record, - ConnectFunc cb, gpointer user_data); -void bluetooth_unregister_server(struct server *server); - -void bluetooth_create_path(const char *dev_addr, const char *adapter_addr, - char *buf, int size); - -int bluetooth_send_with_reply(const char *path, const char *interface, - const char *method, DBusPendingCall **call, - DBusPendingCallNotifyFunction cb, - void *user_data, DBusFreeFunction free_func, - int timeout, int type, ...); -void bluetooth_parse_properties(DBusMessage *reply, const char *property, ...); - -int bluetooth_sap_client_register(struct bluetooth_sap_driver *sap, - struct ofono_modem *modem); -void bluetooth_sap_client_unregister(struct ofono_modem *modem); diff --git a/plugins/dun_gw_bluez4.c b/plugins/dun_gw_bluez4.c deleted file mode 100644 index a1de7a47f623..000000000000 --- a/plugins/dun_gw_bluez4.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * oFono - Open Source Telephony - * - * Copyright (C) 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 - -#define OFONO_API_SUBJECT_TO_CHANGE -#include -#include -#include -#include - -#include "bluez4.h" - -#define DUN_GW_CHANNEL 1 - -static struct server *server; -static guint modemwatch_id; -static GList *modems; - -static const gchar *dun_record = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -"\n"; - -static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data) -{ - struct ofono_emulator *em = user_data; - struct ofono_modem *modem; - int fd; - - DBG(""); - - if (err) { - DBG("%s", err->message); - g_io_channel_shutdown(io, TRUE, NULL); - return; - } - - /* Pick the first powered modem */ - modem = modems->data; - DBG("Picked modem %p for emulator", modem); - - em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_DUN); - if (em == NULL) { - g_io_channel_shutdown(io, TRUE, NULL); - return; - } - - fd = g_io_channel_unix_get_fd(io); - g_io_channel_set_close_on_unref(io, FALSE); - - ofono_emulator_register(em, fd); -} - -static void gprs_watch(struct ofono_atom *atom, - enum ofono_atom_watch_condition cond, - void *data) -{ - struct ofono_modem *modem = data; - - if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) { - modems = g_list_append(modems, modem); - - if (modems->next == NULL) - server = bluetooth_register_server(DUN_GW_CHANNEL, - dun_record, - dun_gw_connect_cb, - NULL); - } else { - modems = g_list_remove(modems, modem); - if (modems == NULL && server != NULL) { - bluetooth_unregister_server(server); - server = NULL; - } - } -} - -static void modem_watch(struct ofono_modem *modem, gboolean added, void *user) -{ - DBG("modem: %p, added: %d", modem, added); - - if (added == FALSE) - return; - - __ofono_modem_add_atom_watch(modem, OFONO_ATOM_TYPE_GPRS, - gprs_watch, modem, NULL); -} - -static void call_modemwatch(struct ofono_modem *modem, void *user) -{ - modem_watch(modem, TRUE, user); -} - -static int dun_gw_init(void) -{ - DBG(""); - - modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL); - - __ofono_modem_foreach(call_modemwatch, NULL); - - return 0; -} - -static void dun_gw_exit(void) -{ - __ofono_modemwatch_remove(modemwatch_id); - g_list_free(modems); - - if (server) { - bluetooth_unregister_server(server); - server = NULL; - } -} - -OFONO_PLUGIN_DEFINE(dun_gw_bluez4, "Dial-up Networking Profile Plugins", - VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT, - dun_gw_init, dun_gw_exit) diff --git a/plugins/hfp_ag_bluez4.c b/plugins/hfp_ag_bluez4.c deleted file mode 100644 index 039b665e14a4..000000000000 --- a/plugins/hfp_ag_bluez4.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * oFono - Open Source Telephony - * - * Copyright (C) 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 - -#define OFONO_API_SUBJECT_TO_CHANGE -#include -#include -#include -#include - -#include "bluez4.h" - -#define HFP_AG_CHANNEL 13 - -static struct server *server; -static guint modemwatch_id; -static GList *modems; -static GHashTable *sim_hash = NULL; - -static const gchar *hfp_ag_record = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -"\n" -" \n" -" \n" -" \n" -"\n"; - -static void hfp_ag_connect_cb(GIOChannel *io, GError *err, gpointer user_data) -{ - struct ofono_modem *modem; - struct ofono_emulator *em; - int fd; - - DBG(""); - - if (err) { - DBG("%s", err->message); - return; - } - - /* Pick the first voicecall capable modem */ - modem = modems->data; - if (modem == NULL) - return; - - DBG("Picked modem %p for emulator", modem); - - em = ofono_emulator_create(modem, OFONO_EMULATOR_TYPE_HFP); - if (em == NULL) - return; - - fd = g_io_channel_unix_get_fd(io); - g_io_channel_set_close_on_unref(io, FALSE); - - ofono_emulator_register(em, fd); -} - -static void sim_state_watch(enum ofono_sim_state new_state, void *data) -{ - struct ofono_modem *modem = data; - - if (new_state != OFONO_SIM_STATE_READY) { - modems = g_list_remove(modems, modem); - if (modems == NULL && server != NULL) { - bluetooth_unregister_server(server); - server = NULL; - } - - return; - } - - if (__ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_VOICECALL) == NULL) - return; - - modems = g_list_append(modems, modem); - - if (modems->next != NULL) - return; - - server = bluetooth_register_server(HFP_AG_CHANNEL, hfp_ag_record, - hfp_ag_connect_cb, NULL); -} - -static gboolean sim_watch_remove(gpointer key, gpointer value, - gpointer user_data) -{ - struct ofono_sim *sim = key; - - ofono_sim_remove_state_watch(sim, GPOINTER_TO_UINT(value)); - - return TRUE; -} - -static void sim_watch(struct ofono_atom *atom, - enum ofono_atom_watch_condition cond, - void *data) -{ - struct ofono_sim *sim = __ofono_atom_get_data(atom); - struct ofono_modem *modem = data; - int watch; - - if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) { - sim_state_watch(OFONO_SIM_STATE_NOT_PRESENT, modem); - - sim_watch_remove(sim, g_hash_table_lookup(sim_hash, sim), NULL); - g_hash_table_remove(sim_hash, sim); - - return; - } - - watch = ofono_sim_add_state_watch(sim, sim_state_watch, modem, NULL); - g_hash_table_insert(sim_hash, sim, GUINT_TO_POINTER(watch)); - sim_state_watch(ofono_sim_get_state(sim), modem); -} - -static void modem_watch(struct ofono_modem *modem, gboolean added, void *user) -{ - DBG("modem: %p, added: %d", modem, added); - - if (added == FALSE) - return; - - __ofono_modem_add_atom_watch(modem, OFONO_ATOM_TYPE_SIM, - sim_watch, modem, NULL); -} - -static void call_modemwatch(struct ofono_modem *modem, void *user) -{ - modem_watch(modem, TRUE, user); -} - -static int hfp_ag_init(void) -{ - sim_hash = g_hash_table_new(g_direct_hash, g_direct_equal); - - modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL); - __ofono_modem_foreach(call_modemwatch, NULL); - - return 0; -} - -static void hfp_ag_exit(void) -{ - __ofono_modemwatch_remove(modemwatch_id); - g_list_free(modems); - g_hash_table_foreach_remove(sim_hash, sim_watch_remove, NULL); - g_hash_table_destroy(sim_hash); - - if (server) { - bluetooth_unregister_server(server); - server = NULL; - } -} - -OFONO_PLUGIN_DEFINE(hfp_ag_bluez4, "Hands-Free Audio Gateway Profile Plugins", - VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT, - hfp_ag_init, hfp_ag_exit) diff --git a/plugins/hfp_hf_bluez4.c b/plugins/hfp_hf_bluez4.c deleted file mode 100644 index fb491a104883..000000000000 --- a/plugins/hfp_hf_bluez4.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * - * oFono - Open Source Telephony - * - * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. - * Copyright (C) 2010 ProFUSION embedded systems - * Copyright (C) 2011 BMW Car IT GmbH. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include - -#define OFONO_API_SUBJECT_TO_CHANGE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "bluez4.h" - -#define BLUEZ_GATEWAY_INTERFACE BLUEZ_SERVICE ".HandsfreeGateway" - -#define HFP_AGENT_INTERFACE "org.bluez.HandsfreeAgent" -#define HFP_AGENT_ERROR_INTERFACE "org.bluez.Error" - -#ifndef DBUS_TYPE_UNIX_FD -#define DBUS_TYPE_UNIX_FD -1 -#endif - -static DBusConnection *connection; -static GHashTable *modem_hash = NULL; - -struct hfp_data { - struct hfp_slc_info info; - char *handsfree_path; - char *handsfree_address; - DBusMessage *slc_msg; - gboolean agent_registered; - DBusPendingCall *call; -}; - -static void hfp_debug(const char *str, void *user_data) -{ - const char *prefix = user_data; - - ofono_info("%s%s", prefix, str); -} - -static void slc_established(gpointer userdata) -{ - struct ofono_modem *modem = userdata; - struct hfp_data *data = ofono_modem_get_data(modem); - DBusMessage *msg; - - ofono_modem_set_powered(modem, TRUE); - - msg = dbus_message_new_method_return(data->slc_msg); - g_dbus_send_message(connection, msg); - dbus_message_unref(data->slc_msg); - data->slc_msg = NULL; - - ofono_info("Service level connection established"); -} - -static void slc_failed(gpointer userdata) -{ - struct ofono_modem *modem = userdata; - struct hfp_data *data = ofono_modem_get_data(modem); - DBusMessage *msg; - - msg = g_dbus_create_error(data->slc_msg, HFP_AGENT_ERROR_INTERFACE - ".Failed", - "HFP Handshake failed"); - g_dbus_send_message(connection, msg); - dbus_message_unref(data->slc_msg); - data->slc_msg = NULL; - - ofono_error("Service level connection failed"); - ofono_modem_set_powered(modem, FALSE); - - g_at_chat_unref(data->info.chat); - data->info.chat = NULL; -} - -static void hfp_disconnected_cb(gpointer user_data) -{ - struct ofono_modem *modem = user_data; - struct hfp_data *data = ofono_modem_get_data(modem); - - ofono_modem_set_powered(modem, FALSE); - - g_at_chat_unref(data->info.chat); - data->info.chat = NULL; -} - -/* either oFono or Phone could request SLC connection */ -static int service_level_connection(struct ofono_modem *modem, int fd) -{ - struct hfp_data *data = ofono_modem_get_data(modem); - GIOChannel *io; - GAtSyntax *syntax; - GAtChat *chat; - - io = g_io_channel_unix_new(fd); - if (io == NULL) { - ofono_error("Service level connection failed: %s (%d)", - strerror(errno), errno); - return -EIO; - } - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(io, syntax); - g_at_syntax_unref(syntax); - g_io_channel_unref(io); - - if (chat == NULL) - return -ENOMEM; - - g_at_chat_set_disconnect_function(chat, hfp_disconnected_cb, modem); - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, hfp_debug, ""); - - data->info.chat = chat; - hfp_slc_establish(&data->info, slc_established, slc_failed, modem); - - return -EINPROGRESS; -} - -static DBusMessage *hfp_agent_new_connection(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - int fd, err; - struct ofono_modem *modem = data; - struct hfp_data *hfp_data = ofono_modem_get_data(modem); - guint16 version; - - if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, &fd, - DBUS_TYPE_UINT16, &version, DBUS_TYPE_INVALID)) - return __ofono_error_invalid_args(msg); - - hfp_slc_info_init(&hfp_data->info, version); - - err = service_level_connection(modem, fd); - if (err < 0 && err != -EINPROGRESS) - return __ofono_error_failed(msg); - - hfp_data->slc_msg = msg; - dbus_message_ref(msg); - - return NULL; -} - -static DBusMessage *hfp_agent_release(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct ofono_modem *modem = data; - struct hfp_data *hfp_data = ofono_modem_get_data(modem); - const char *obj_path = ofono_modem_get_path(modem); - - g_dbus_unregister_interface(connection, obj_path, HFP_AGENT_INTERFACE); - hfp_data->agent_registered = FALSE; - - g_hash_table_remove(modem_hash, hfp_data->handsfree_path); - ofono_modem_remove(modem); - - return dbus_message_new_method_return(msg); -} - -static const GDBusMethodTable agent_methods[] = { - { GDBUS_ASYNC_METHOD("NewConnection", - GDBUS_ARGS({ "fd", "h" }, { "version", "q" }), - NULL, hfp_agent_new_connection) }, - { GDBUS_METHOD("Release", NULL, NULL, hfp_agent_release) }, - { } -}; - -static int hfp_hf_probe(const char *device, const char *dev_addr, - const char *adapter_addr, const char *alias) -{ - struct ofono_modem *modem; - struct hfp_data *data; - char buf[256]; - - /* We already have this device in our hash, ignore */ - if (g_hash_table_lookup(modem_hash, device) != NULL) - return -EALREADY; - - ofono_info("Using device: %s, devaddr: %s, adapter: %s", - device, dev_addr, adapter_addr); - - strcpy(buf, "hfp/"); - bluetooth_create_path(dev_addr, adapter_addr, buf + 4, sizeof(buf) - 4); - - modem = ofono_modem_create(buf, "hfp"); - if (modem == NULL) - return -ENOMEM; - - data = g_try_new0(struct hfp_data, 1); - if (data == NULL) - goto free; - - data->handsfree_path = g_strdup(device); - if (data->handsfree_path == NULL) - goto free; - - data->handsfree_address = g_strdup(dev_addr); - if (data->handsfree_address == NULL) - goto free; - - ofono_modem_set_data(modem, data); - ofono_modem_set_name(modem, alias); - ofono_modem_register(modem); - - g_hash_table_insert(modem_hash, g_strdup(device), modem); - - return 0; - -free: - if (data != NULL) - g_free(data->handsfree_path); - - g_free(data); - ofono_modem_remove(modem); - - return -ENOMEM; -} - -static gboolean hfp_remove_modem(gpointer key, gpointer value, - gpointer user_data) -{ - struct ofono_modem *modem = value; - const char *device = key; - const char *prefix = user_data; - - if (prefix && g_str_has_prefix(device, prefix) == FALSE) - return FALSE; - - ofono_modem_remove(modem); - - return TRUE; -} - -static void hfp_hf_remove(const char *prefix) -{ - DBG("%s", prefix); - - if (modem_hash == NULL) - return; - - g_hash_table_foreach_remove(modem_hash, hfp_remove_modem, - (gpointer) prefix); -} - -static void hfp_hf_set_alias(const char *device, const char *alias) -{ - struct ofono_modem *modem; - - if (device == NULL || alias == NULL) - return; - - modem = g_hash_table_lookup(modem_hash, device); - if (modem == NULL) - return; - - ofono_modem_set_name(modem, alias); -} - -static int hfp_register_ofono_handsfree(struct ofono_modem *modem) -{ - const char *obj_path = ofono_modem_get_path(modem); - struct hfp_data *data = ofono_modem_get_data(modem); - DBusMessage *msg; - - DBG("Registering oFono Agent to bluetooth daemon"); - - msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "RegisterAgent"); - if (msg == NULL) - return -ENOMEM; - - dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_INVALID); - - g_dbus_send_message(connection, msg); - return 0; -} - -static int hfp_unregister_ofono_handsfree(struct ofono_modem *modem) -{ - const char *obj_path = ofono_modem_get_path(modem); - struct hfp_data *data = ofono_modem_get_data(modem); - DBusMessage *msg; - - DBG("Unregistering oFono Agent from bluetooth daemon"); - - msg = dbus_message_new_method_call(BLUEZ_SERVICE, data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "UnregisterAgent"); - if (msg == NULL) - return -ENOMEM; - - dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &obj_path, - DBUS_TYPE_INVALID); - - g_dbus_send_message(connection, msg); - return 0; -} - -static int hfp_probe(struct ofono_modem *modem) -{ - const char *obj_path = ofono_modem_get_path(modem); - struct hfp_data *data = ofono_modem_get_data(modem); - - if (data == NULL) - return -EINVAL; - - g_dbus_register_interface(connection, obj_path, HFP_AGENT_INTERFACE, - agent_methods, NULL, NULL, modem, NULL); - - data->agent_registered = TRUE; - - if (hfp_register_ofono_handsfree(modem) != 0) - return -EINVAL; - - return 0; -} - -static void hfp_remove(struct ofono_modem *modem) -{ - struct hfp_data *data = ofono_modem_get_data(modem); - const char *obj_path = ofono_modem_get_path(modem); - - if (data->call != NULL) - dbus_pending_call_cancel(data->call); - - if (g_dbus_unregister_interface(connection, obj_path, - HFP_AGENT_INTERFACE)) - hfp_unregister_ofono_handsfree(modem); - - g_free(data->handsfree_address); - g_free(data->handsfree_path); - g_free(data); - - ofono_modem_set_data(modem, NULL); -} - -static void hfp_connect_reply(DBusPendingCall *call, gpointer user_data) -{ - struct ofono_modem *modem = user_data; - struct hfp_data *data = ofono_modem_get_data(modem); - DBusError derr; - DBusMessage *reply, *msg; - - reply = dbus_pending_call_steal_reply(call); - - if (ofono_modem_get_powered(modem)) - goto done; - - dbus_error_init(&derr); - if (!dbus_set_error_from_message(&derr, reply)) - goto done; - - DBG("Connect reply: %s", derr.message); - - if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY)) { - msg = dbus_message_new_method_call(BLUEZ_SERVICE, - data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "Disconnect"); - if (msg == NULL) - ofono_error("Disconnect failed"); - else - g_dbus_send_message(connection, msg); - } - - ofono_modem_set_powered(modem, FALSE); - - dbus_error_free(&derr); - -done: - dbus_message_unref(reply); - data->call = NULL; -} - -/* power up hardware */ -static int hfp_enable(struct ofono_modem *modem) -{ - struct hfp_data *data = ofono_modem_get_data(modem); - int status; - - DBG("%p", modem); - - status = bluetooth_send_with_reply(data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "Connect", - &data->call, hfp_connect_reply, - modem, NULL, - DBUS_TIMEOUT, DBUS_TYPE_INVALID); - - if (status < 0) - return -EINVAL; - - return -EINPROGRESS; -} - -static void hfp_power_down(DBusPendingCall *call, gpointer user_data) -{ - struct ofono_modem *modem = user_data; - struct hfp_data *data = ofono_modem_get_data(modem); - DBusMessage *reply; - DBusError derr; - - reply = dbus_pending_call_steal_reply(call); - - dbus_error_init(&derr); - if (dbus_set_error_from_message(&derr, reply)) { - DBG("Disconnect reply: %s", derr.message); - dbus_error_free(&derr); - goto done; - } - - ofono_modem_set_powered(modem, FALSE); - -done: - dbus_message_unref(reply); - data->call = NULL; -} - -static int hfp_disable(struct ofono_modem *modem) -{ - struct hfp_data *data = ofono_modem_get_data(modem); - int status; - - DBG("%p", modem); - - g_at_chat_unref(data->info.chat); - data->info.chat = NULL; - - if (data->agent_registered) { - status = bluetooth_send_with_reply(data->handsfree_path, - BLUEZ_GATEWAY_INTERFACE, "Disconnect", - &data->call, hfp_power_down, - modem, NULL, - DBUS_TIMEOUT, DBUS_TYPE_INVALID); - - if (status < 0) - return -EINVAL; - } - - return -EINPROGRESS; -} - -static void hfp_pre_sim(struct ofono_modem *modem) -{ - struct hfp_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - ofono_devinfo_create(modem, 0, "hfpmodem", data->handsfree_address); - ofono_voicecall_create(modem, 0, "hfpmodem", &data->info); - ofono_netreg_create(modem, 0, "hfpmodem", &data->info); - ofono_call_volume_create(modem, 0, "hfpmodem", &data->info); - ofono_handsfree_create(modem, 0, "hfpmodem", &data->info); - ofono_siri_create(modem, 0, "hfpmodem", &data->info); -} - -static void hfp_post_sim(struct ofono_modem *modem) -{ - DBG("%p", modem); -} - -static struct ofono_modem_driver hfp_driver = { - .name = "hfp", - .modem_type = OFONO_MODEM_TYPE_HFP, - .probe = hfp_probe, - .remove = hfp_remove, - .enable = hfp_enable, - .disable = hfp_disable, - .pre_sim = hfp_pre_sim, - .post_sim = hfp_post_sim, -}; - -static struct bluetooth_profile hfp_hf = { - .name = "hfp_hf", - .probe = hfp_hf_probe, - .remove = hfp_hf_remove, - .set_alias = hfp_hf_set_alias, -}; - -static int hfp_init(void) -{ - int err; - - if (DBUS_TYPE_UNIX_FD < 0) - return -EBADF; - - connection = ofono_dbus_get_connection(); - - err = ofono_modem_driver_register(&hfp_driver); - if (err < 0) - return err; - - err = bluetooth_register_uuid(HFP_AG_UUID, &hfp_hf); - if (err < 0) { - ofono_modem_driver_unregister(&hfp_driver); - return err; - } - - modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - - return 0; -} - -static void hfp_exit(void) -{ - bluetooth_unregister_uuid(HFP_AG_UUID); - ofono_modem_driver_unregister(&hfp_driver); - - g_hash_table_destroy(modem_hash); -} - -OFONO_PLUGIN_DEFINE(hfp_bluez4, "Hands-Free Profile Plugins", VERSION, - OFONO_PLUGIN_PRIORITY_DEFAULT, hfp_init, hfp_exit) diff --git a/plugins/sap.c b/plugins/sap.c deleted file mode 100644 index d1913fb58e1d..000000000000 --- a/plugins/sap.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * - * oFono - Open Source Telephony - * - * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. - * Copyright (C) 2010-2011 ProFUSION embedded systems - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 -#include -#include - -#define OFONO_API_SUBJECT_TO_CHANGE -#include -#include -#include - -#include "bluez4.h" -#include "util.h" - -#ifndef DBUS_TYPE_UNIX_FD -#define DBUS_TYPE_UNIX_FD -1 -#endif - -#define BLUEZ_SERIAL_INTERFACE BLUEZ_SERVICE ".Serial" - -static DBusConnection *connection; -static GHashTable *modem_hash = NULL; -static struct ofono_modem *sap_hw_modem = NULL; -static struct bluetooth_sap_driver *sap_hw_driver = NULL; - -struct sap_data { - struct ofono_modem *hw_modem; - struct bluetooth_sap_driver *sap_driver; - DBusPendingCall *call; -}; - -int bluetooth_sap_client_register(struct bluetooth_sap_driver *sap, - struct ofono_modem *modem) -{ - if (sap_hw_modem != NULL) - return -EPERM; - - sap_hw_modem = modem; - sap_hw_driver = sap; - - bluetooth_get_properties(); - - return 0; -} - -void bluetooth_sap_client_unregister(struct ofono_modem *modem) -{ - GHashTableIter iter; - gpointer key, value; - - if (sap_hw_modem == NULL) - return; - - g_hash_table_iter_init(&iter, modem_hash); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - g_hash_table_iter_remove(&iter); - - ofono_modem_remove(value); - } - - sap_hw_modem = NULL; - sap_hw_driver = NULL; -} - -static int sap_probe(struct ofono_modem *modem) -{ - struct sap_data *data; - - DBG("%p", modem); - - data = g_try_new0(struct sap_data, 1); - if (data == NULL) - return -ENOMEM; - - ofono_modem_set_data(modem, data); - - return 0; -} - -static void sap_remove(struct ofono_modem *modem) -{ - struct sap_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - if (data->call != NULL) - dbus_pending_call_cancel(data->call); - - g_free(data); - - ofono_modem_set_data(modem, NULL); -} - -static void sap_connect_reply(DBusPendingCall *call, gpointer user_data) -{ - struct ofono_modem *modem = user_data; - struct sap_data *data = ofono_modem_get_data(modem); - DBusError derr; - DBusMessage *reply; - int fd, err; - - DBG(""); - - reply = dbus_pending_call_steal_reply(call); - - data->call = NULL; - - if (ofono_modem_get_powered(modem)) - goto done; - - dbus_error_init(&derr); - if (dbus_set_error_from_message(&derr, reply)) { - - DBG("Connect reply: %s", derr.message); - - dbus_error_free(&derr); - goto done; - } - - if (!dbus_message_get_args(reply, NULL, DBUS_TYPE_UNIX_FD, &fd, - DBUS_TYPE_INVALID)) - goto done; - - data->hw_modem = sap_hw_modem; - data->sap_driver = sap_hw_driver; - - err = data->sap_driver->enable(data->hw_modem, modem, fd); - if (!err || err == -EINPROGRESS) { - dbus_message_unref(reply); - return; - } - -done: - ofono_modem_set_powered(modem, FALSE); - dbus_message_unref(reply); -} - -/* power up hardware */ -static int sap_enable(struct ofono_modem *modem) -{ - struct sap_data *data = ofono_modem_get_data(modem); - DBusPendingCall *call; - int status; - const char *str = "sap"; - const char *server_path = ofono_modem_get_string(modem, "ServerPath"); - - DBG("%p", modem); - - status = bluetooth_send_with_reply(server_path, BLUEZ_SERIAL_INTERFACE, - "ConnectFD", &call, sap_connect_reply, - modem, NULL, DBUS_TIMEOUT, - DBUS_TYPE_STRING, &str, - DBUS_TYPE_INVALID); - - if (status < 0) - return -EINVAL; - - data->call = call; - - return -EINPROGRESS; -} - -static int sap_disable(struct ofono_modem *modem) -{ - struct sap_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - return data->sap_driver->disable(data->hw_modem); -} - -static void sap_pre_sim(struct ofono_modem *modem) -{ - struct sap_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - data->sap_driver->pre_sim(data->hw_modem); -} - -static void sap_post_sim(struct ofono_modem *modem) -{ - struct sap_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - data->sap_driver->post_sim(data->hw_modem); -} - -static void sap_set_online(struct ofono_modem *modem, ofono_bool_t online, - ofono_modem_online_cb_t cb, void *user_data) -{ - struct sap_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - data->sap_driver->set_online(data->hw_modem, online, cb, user_data); -} - -static void sap_post_online(struct ofono_modem *modem) -{ - struct sap_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - data->sap_driver->post_online(data->hw_modem); -} - -static int bluetooth_sap_probe(const char *device, const char *dev_addr, - const char *adapter_addr, const char *alias) -{ - struct ofono_modem *modem; - char buf[256]; - - if (sap_hw_modem == NULL) - return -ENODEV; - - /* We already have this device in our hash, ignore */ - if (g_hash_table_lookup(modem_hash, device) != NULL) - return -EALREADY; - - ofono_info("Using device: %s, devaddr: %s, adapter: %s", - device, dev_addr, adapter_addr); - - strcpy(buf, "sap/"); - bluetooth_create_path(dev_addr, adapter_addr, buf + 4, - sizeof(buf) - 4); - - modem = ofono_modem_create(buf, "sap"); - if (modem == NULL) - return -ENOMEM; - - ofono_modem_set_string(modem, "ServerPath", device); - ofono_modem_set_name(modem, alias); - ofono_modem_register(modem); - - g_hash_table_insert(modem_hash, g_strdup(device), modem); - - return 0; -} - -static void bluetooth_sap_remove(const char *prefix) -{ - GHashTableIter iter; - gpointer key, value; - - DBG("%s", prefix); - - if (modem_hash == NULL) - return; - - g_hash_table_iter_init(&iter, modem_hash); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - if (prefix && g_str_has_prefix((char *)key, prefix) == FALSE) - continue; - - g_hash_table_iter_remove(&iter); - - ofono_modem_remove(value); - } -} - -static void bluetooth_sap_set_alias(const char *device, const char *alias) -{ - struct ofono_modem *modem; - - if (device == NULL || alias == NULL) - return; - - modem = g_hash_table_lookup(modem_hash, device); - if (modem == NULL) - return; - - ofono_modem_set_name(modem, alias); -} - -static struct ofono_modem_driver sap_driver = { - .name = "sap", - .modem_type = OFONO_MODEM_TYPE_SAP, - .probe = sap_probe, - .remove = sap_remove, - .enable = sap_enable, - .disable = sap_disable, - .pre_sim = sap_pre_sim, - .post_sim = sap_post_sim, - .set_online = sap_set_online, - .post_online = sap_post_online, -}; - -static struct bluetooth_profile sap = { - .name = "sap", - .probe = bluetooth_sap_probe, - .remove = bluetooth_sap_remove, - .set_alias = bluetooth_sap_set_alias, -}; - -static int sap_init(void) -{ - int err; - - if (DBUS_TYPE_UNIX_FD < 0) - return -EBADF; - - connection = ofono_dbus_get_connection(); - - err = ofono_modem_driver_register(&sap_driver); - if (err < 0) - return err; - - err = bluetooth_register_uuid(SAP_UUID, &sap); - if (err < 0) { - ofono_modem_driver_unregister(&sap_driver); - return err; - } - - modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - - return 0; -} - -static void sap_exit(void) -{ - DBG(""); - - bluetooth_unregister_uuid(SAP_UUID); - ofono_modem_driver_unregister(&sap_driver); - g_hash_table_destroy(modem_hash); - modem_hash = NULL; -} - -OFONO_PLUGIN_DEFINE(sap, "Sim Access Profile Plugins", VERSION, - OFONO_PLUGIN_PRIORITY_DEFAULT, sap_init, sap_exit)