mirror of git://git.sysmocom.de/ofono
dundee: Add Bluetooth DUN driver
parent
a73f83df57
commit
405be6ea13
|
@ -687,10 +687,10 @@ if DUNDEE
|
|||
|
||||
sbin_PROGRAMS += dundee/dundee
|
||||
|
||||
dundee_dundee_SOURCES = $(gdbus_sources) $(gatchat_sources) \
|
||||
src/log.c src/dbus.c \
|
||||
dundee_dundee_SOURCES = $(gdbus_sources) $(gatchat_sources) $(btio_sources) \
|
||||
src/log.c src/dbus.c plugins/bluetooth.c \
|
||||
dundee/dundee.h dundee/main.c dundee/dbus.c \
|
||||
dundee/manager.c dundee/device.c
|
||||
dundee/manager.c dundee/device.c dundee/bluetooth.c
|
||||
|
||||
dundee_dundee_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
|
||||
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "plugins/bluetooth.h"
|
||||
|
||||
#include "dundee.h"
|
||||
|
||||
static GHashTable *bluetooth_hash;
|
||||
|
||||
struct bluetooth_device {
|
||||
struct dundee_device *device;
|
||||
|
||||
char *path;
|
||||
char *address;
|
||||
char *name;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
g_free(cbd);
|
||||
|
||||
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -139,3 +139,6 @@ void __dundee_device_foreach(dundee_device_foreach_func cb, void *userdata);
|
|||
const char *__dundee_device_get_path(struct dundee_device *device);
|
||||
void __dundee_device_append_properties(struct dundee_device *device,
|
||||
DBusMessageIter *dict);
|
||||
|
||||
int __dundee_bluetooth_init(void);
|
||||
void __dundee_bluetooth_cleanup(void);
|
||||
|
|
|
@ -234,9 +234,11 @@ int main(int argc, char **argv)
|
|||
|
||||
__dundee_manager_init();
|
||||
__dundee_device_init();
|
||||
__dundee_bluetooth_init();
|
||||
|
||||
g_main_loop_run(event_loop);
|
||||
|
||||
__dundee_bluetooth_cleanup();
|
||||
__dundee_device_cleanup();
|
||||
__dundee_manager_cleanup();
|
||||
|
||||
|
|
Loading…
Reference in New Issue