From a518536785ff3f96234ce8bfdfe002d6eee330d5 Mon Sep 17 00:00:00 2001 From: Raymond Liu Date: Tue, 20 Jan 2009 13:47:12 +0800 Subject: [PATCH] Add framework code for SAP --- Makefile.am | 2 +- acinclude.m4 | 6 ++ configure.ac | 1 + plugins/Makefile.am | 2 + sap/Makefile.am | 21 +++++ sap/device.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++ sap/device.h | 28 +++++++ sap/main.c | 59 ++++++++++++++ sap/manager.c | 130 ++++++++++++++++++++++++++++++ sap/manager.h | 26 ++++++ 10 files changed, 493 insertions(+), 1 deletions(-) create mode 100644 sap/Makefile.am create mode 100644 sap/device.c create mode 100644 sap/device.h create mode 100644 sap/main.c create mode 100644 sap/manager.c create mode 100644 sap/manager.h diff --git a/Makefile.am b/Makefile.am index f2d1ca7..c6899d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = include lib sbc gdbus common src client\ - plugins network serial input audio \ + plugins network serial input audio sap \ tools rfcomm compat cups test scripts doc EXTRA_DIST = bluez.m4 diff --git a/acinclude.m4 b/acinclude.m4 index 372833e..704c9ee 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -186,6 +186,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [ input_enable=yes serial_enable=yes network_enable=yes + sap_enable=yes service_enable=yes tools_enable=yes hidd_enable=no @@ -226,6 +227,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [ audio_enable=${enableval} ]) + AC_ARG_ENABLE(sap, AC_HELP_STRING([--disable-sap], [disable sap plugin]), [ + sap_enable=${enableval} + ]) + AC_ARG_ENABLE(service, AC_HELP_STRING([--disable-service], [disable service plugin]), [ service_enable=${enableval} ]) @@ -344,6 +349,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [ AM_CONDITIONAL(INPUTPLUGIN, test "${input_enable}" = "yes") AM_CONDITIONAL(SERIALPLUGIN, test "${serial_enable}" = "yes") AM_CONDITIONAL(NETWORKPLUGIN, test "${network_enable}" = "yes") + AM_CONDITIONAL(SAPPLUGIN, test "${sap_enable}" = "yes") AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes") AM_CONDITIONAL(HIDD, test "${hidd_enable}" = "yes") AM_CONDITIONAL(PAND, test "${pand_enable}" = "yes") diff --git a/configure.ac b/configure.ac index 84a6234..bc7cf6b 100644 --- a/configure.ac +++ b/configure.ac @@ -55,6 +55,7 @@ AC_OUTPUT([ serial/Makefile input/Makefile audio/Makefile + sap/Makefile tools/Makefile rfcomm/Makefile compat/Makefile diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 3b258a3..7ad76fe 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -46,6 +46,7 @@ all-local: @$(LN_S) -f $(top_srcdir)/audio/.libs/audio.so @$(LN_S) -f $(top_srcdir)/serial/.libs/serial.so @$(LN_S) -f $(top_srcdir)/network/.libs/network.so + @$(LN_S) -f $(top_srcdir)/sap/.libs/sap.so @$(LN_S) -f .libs/service.so @$(LN_S) -f .libs/hal.so @@ -56,3 +57,4 @@ clean-local: @rm -f serial.so @rm -f audio.so @rm -f input.so + @rm -f sap.so diff --git a/sap/Makefile.am b/sap/Makefile.am new file mode 100644 index 0000000..aad95f3 --- /dev/null +++ b/sap/Makefile.am @@ -0,0 +1,21 @@ + +if SAPPLUGIN +plugindir = $(libdir)/bluetooth/plugins + +plugin_LTLIBRARIES = sap.la + +sap_la_SOURCES = main.c manager.h manager.c \ + device.h device.c + +LDADD = $(top_builddir)/common/libhelper.a \ + @GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ +endif + +AM_LDFLAGS = -module -avoid-version -no-undefined \ + -export-symbols-regex bluetooth_plugin_desc + +AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@ + +INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/src + +MAINTAINERCLEANFILES = Makefile.in diff --git a/sap/device.c b/sap/device.c new file mode 100644 index 0000000..b3c4a0a --- /dev/null +++ b/sap/device.c @@ -0,0 +1,219 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2009 Intel Corporation + * Copyright (C) 2004-2009 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include + +#include +#include + +#include "../src/dbus-common.h" + +#include "logging.h" +#include "glib-helper.h" + +#include "device.h" + +#define SAP_CLIENT_INTERFACE "org.bluez.SimAccess" + +struct sap_device { + DBusConnection *conn; + bdaddr_t src; /* Source (local) address */ + bdaddr_t dst; /* Destination address */ + char *path; /* Device path */ + uint8_t channel; /* SAP server's rfcomm channel */ +}; + +static GSList *devices = NULL; + +static struct sap_device *find_device(GSList *devices, const char *path) +{ + GSList *l; + + for (l = devices; l != NULL; l = l->next) { + struct sap_device *device = l->data; + + if (!strcmp(device->path, path)) + return device; + } + + return NULL; +} + +static void sap_device_free(struct sap_device *device) +{ + g_free(device->path); + if (device->conn) + dbus_connection_unref(device->conn); + g_free(device); +} + +static void path_unregister(void *data) +{ + struct sap_device *device = data; + + info("Unregistered interface %s on path %s", SAP_CLIENT_INTERFACE, + device->path); + + devices = g_slist_remove(devices, device); + sap_device_free(device); +} + +static DBusMessage *sap_connect(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static DBusMessage *sap_disconnect(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static DBusMessage *sap_send_apdu(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static DBusMessage *sap_power_on(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static DBusMessage *sap_power_off(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static DBusMessage *sap_reset(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static DBusMessage *sap_set_protocol(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static DBusMessage *sap_get_properties(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return NULL; +} + +static GDBusMethodTable sap_methods[] = { + { "Connect", "", "", sap_connect, + G_DBUS_METHOD_FLAG_ASYNC }, + { "Disconnect", "", "", sap_disconnect, + G_DBUS_METHOD_FLAG_ASYNC }, + { "SendAPDU", "ay", "ay", sap_send_apdu, + G_DBUS_METHOD_FLAG_ASYNC }, + { "PowerOff", "", "", sap_power_off, + G_DBUS_METHOD_FLAG_DEPRECATED }, + { "PowerOn", "", "", sap_power_on, + G_DBUS_METHOD_FLAG_DEPRECATED }, + { "Reset", "", "", sap_reset, + G_DBUS_METHOD_FLAG_DEPRECATED }, + { "SetProtocol", "y", "", sap_set_protocol, + G_DBUS_METHOD_FLAG_DEPRECATED }, + { "GetProperties", "", "a{sv}",sap_get_properties }, + { NULL, NULL, NULL, NULL } +}; + +static GDBusSignalTable sap_signals[] = { + { "PropertyChanged", "sv" }, + { NULL, NULL } +}; + +static struct sap_device *create_sap_device(DBusConnection *conn, + const char *path, bdaddr_t *src, + bdaddr_t *dst, uint8_t channel) +{ + struct sap_device *device; + + device = g_new0(struct sap_device, 1); + device->conn = dbus_connection_ref(conn); + bacpy(&device->dst, dst); + bacpy(&device->src, src); + device->path = g_strdup(path); + device->channel = channel; + + if (!g_dbus_register_interface(conn, path, + SAP_CLIENT_INTERFACE, + sap_methods, sap_signals, NULL, + device, path_unregister)) { + error("D-Bus failed to register %s interface", + SAP_CLIENT_INTERFACE); + sap_device_free(device); + return NULL; + } + + info("Registered interface %s on path %s", + SAP_CLIENT_INTERFACE, path); + + return device; +} + +int sap_device_register(DBusConnection *conn, const char *path, bdaddr_t *src, + bdaddr_t *dst, const char *uuid, uint8_t channel) +{ + struct sap_device *device; + + device = find_device(devices, path); + if (!device) { + device = create_sap_device(conn, path, src, dst, channel); + if (!device) + return -1; + devices = g_slist_append(devices, device); + } + + return 0; +} + +int sap_device_unregister(const char *path) +{ + struct sap_device *device; + + device = find_device(devices, path); + if (!device) + return -ENOENT; + + g_dbus_unregister_interface(device->conn, path, SAP_CLIENT_INTERFACE); + + return 0; +} diff --git a/sap/device.h b/sap/device.h new file mode 100644 index 0000000..e9f95b1 --- /dev/null +++ b/sap/device.h @@ -0,0 +1,28 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2009 Intel Corporation + * Copyright (C) 2004-2009 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +int sap_device_register(DBusConnection *conn, const char *path, bdaddr_t *src, + bdaddr_t *dst, const char *name, uint8_t channel); + +int sap_device_unregister(const char *path); diff --git a/sap/main.c b/sap/main.c new file mode 100644 index 0000000..f7b5857 --- /dev/null +++ b/sap/main.c @@ -0,0 +1,59 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2009 Intel Corporation + * Copyright (C) 2004-2009 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "plugin.h" +#include "manager.h" + +static DBusConnection *connection; + +static int sap_init(void) +{ + connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (connection == NULL) + return -EIO; + + if (sap_manager_init(connection) < 0) { + dbus_connection_unref(connection); + return -EIO; + } + + return 0; +} + +static void sap_exit(void) +{ + sap_manager_exit(); + + dbus_connection_unref(connection); +} + +BLUETOOTH_PLUGIN_DEFINE("sap", sap_init, sap_exit) diff --git a/sap/manager.c b/sap/manager.c new file mode 100644 index 0000000..90ff789 --- /dev/null +++ b/sap/manager.c @@ -0,0 +1,130 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2009 Intel Corporation + * Copyright (C) 2004-2009 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include + +#include + +#include "logging.h" +#include "../src/adapter.h" +#include "../src/device.h" + +#include "manager.h" +#include "device.h" + + +#define SAP_UUID_STR "0000112D-0000-1000-8000-00805F9B34FB" + +static DBusConnection *connection = NULL; + +static int sap_client_probe(struct btd_device *device, const char *uuid) +{ + struct btd_adapter *adapter = device_get_adapter(device); + const gchar *path = device_get_path(device); + sdp_list_t *protos; + int ch; + bdaddr_t src, dst; + const sdp_record_t *rec; + + DBG("path %s: %s", path, uuid); + + rec = btd_device_get_record(device, uuid); + if (!rec) + return -EINVAL; + + if (sdp_get_access_protos(rec, &protos) < 0) + return -EINVAL; + + ch = sdp_get_proto_port(protos, RFCOMM_UUID); + sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); + sdp_list_free(protos, NULL); + + if (ch < 1 || ch > 30) { + error("Channel out of range: %d", ch); + return -EINVAL; + } + + adapter_get_address(adapter, &src); + device_get_address(device, &dst); + + return sap_device_register(connection, path, &src, &dst, uuid, ch); +} + +static void sap_client_remove(struct btd_device *device) +{ + const gchar *path = device_get_path(device); + + DBG("path %s", path); + + sap_device_unregister(path); +} + + +static int client_probe(struct btd_device *device, GSList *uuids) +{ + while (uuids) { + sap_client_probe(device, uuids->data); + uuids = uuids->next; + } + + return 0; +} + +static void client_remove(struct btd_device *device) +{ + return sap_client_remove(device); +} + +static struct btd_device_driver sap_client_driver = { + .name = "sap-client", + .uuids = BTD_UUIDS(SAP_UUID_STR), + .probe = client_probe, + .remove = client_remove, +}; + +int sap_manager_init(DBusConnection *conn) +{ + connection = dbus_connection_ref(conn); + + btd_register_device_driver(&sap_client_driver); + + return 0; +} + +void sap_manager_exit(void) +{ + btd_unregister_device_driver(&sap_client_driver); + + dbus_connection_unref(connection); + connection = NULL; +} diff --git a/sap/manager.h b/sap/manager.h new file mode 100644 index 0000000..f9162a3 --- /dev/null +++ b/sap/manager.h @@ -0,0 +1,26 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2009 Intel Corporation + * Copyright (C) 2004-2009 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +int sap_manager_init(DBusConnection *conn); +void sap_manager_exit(void); -- 1.5.6.3