⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 device.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2006-2007  Nokia Corporation *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org> * * *  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 <config.h>#endif#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/param.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <glib.h>#include <dbus/dbus.h>#include <gdbus.h>#include "hcid.h"#include "sdpd.h"#include "logging.h"#include "textfile.h"#include "adapter.h"#include "device.h"#include "dbus-common.h"#include "dbus-hci.h"#include "error.h"#include "glib-helper.h"#include "agent.h"#include "sdp-xml.h"#include "driver.h"#define DEFAULT_XML_BUF_SIZE	1024#define DISCONNECT_TIMER	2#define DEVICE_INTERFACE "org.bluez.Device"struct btd_driver_data {	struct btd_device_driver *driver;	void *priv;};struct btd_device {	gchar		*address;	gchar		*path;	struct adapter	*adapter;	GSList		*uuids;	GSList		*drivers;		/* List of driver_data */	gboolean	temporary;	struct agent	*agent;	guint		disconn_timer;	int		discov_active;		/* Service discovery active */	char		*discov_requestor;	/* discovery requestor unique name */	guint		discov_listener;	/* For Secure Simple Pairing */	uint8_t		cap;	uint8_t		auth;};struct browse_req {	DBusConnection *conn;	DBusMessage *msg;	struct btd_device *device;	GSList *uuids_added;	GSList *uuids_removed;	int search_uuid;	gboolean browse;};static uint16_t uuid_list[] = {	PUBLIC_BROWSE_GROUP,	HID_SVCLASS_ID,	GENERIC_AUDIO_SVCLASS_ID,	ADVANCED_AUDIO_SVCLASS_ID,	AV_REMOTE_SVCLASS_ID,	0};static void device_free(gpointer user_data){	struct btd_device *device = user_data;	if (device->agent)		agent_destroy(device->agent, FALSE);	g_slist_foreach(device->uuids, (GFunc) g_free, NULL);	g_slist_free(device->uuids);	if (device->disconn_timer)		g_source_remove(device->disconn_timer);	g_free(device->address);	g_free(device->path);	g_free(device);}static gboolean device_is_paired(struct btd_device *device){	struct adapter *adapter = device->adapter;	char filename[PATH_MAX + 1], *str;	gboolean ret;	const gchar *source = adapter_get_address(adapter);	create_name(filename, PATH_MAX, STORAGEDIR,			source, "linkkeys");	str = textfile_caseget(filename, device->address);	ret = str ? TRUE : FALSE;	g_free(str);	return ret;}static char *device_get_name(struct btd_device *device){	struct adapter *adapter = device->adapter;	char filename[PATH_MAX + 1];	const gchar *source = adapter_get_address(adapter);	create_name(filename, PATH_MAX, STORAGEDIR, source, "names");	return textfile_caseget(filename, device->address);}static DBusMessage *get_properties(DBusConnection *conn,				DBusMessage *msg, void *user_data){	struct btd_device *device = user_data;	struct adapter *adapter = device->adapter;	DBusMessage *reply;	DBusMessageIter iter;	DBusMessageIter dict;	bdaddr_t src, dst;	char path[MAX_PATH_LENGTH];	char buf[64];	const char *ptr;	char *name, *ppath, **uuids;	dbus_bool_t boolean;	uint32_t class;	int i;	GSList *l;	uint16_t dev_id = adapter_get_dev_id(adapter);	const gchar *source = adapter_get_address(adapter);	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);	/* Address */	dbus_message_iter_append_dict_entry(&dict, "Address", DBUS_TYPE_STRING,			&device->address);	/* Name */	name = device_get_name(device);	if (name) {		dbus_message_iter_append_dict_entry(&dict, "Name",				DBUS_TYPE_STRING, &name);	}	str2ba(source, &src);	str2ba(device->address, &dst);	/* Class */	if (read_remote_class(&src, &dst, &class) == 0) {		dbus_message_iter_append_dict_entry(&dict, "Class",				DBUS_TYPE_UINT32, &class);	}	/* Alias */	if (get_device_alias(dev_id, &dst, buf, sizeof(buf)) > 0) {		ptr = buf;		dbus_message_iter_append_dict_entry(&dict, "Alias",				DBUS_TYPE_STRING, &ptr);	} else if (name) {		dbus_message_iter_append_dict_entry(&dict, "Alias",				DBUS_TYPE_STRING, &name);		free(name);	}	/* Paired */	boolean = device_is_paired(device);	dbus_message_iter_append_dict_entry(&dict, "Paired",			DBUS_TYPE_BOOLEAN, &boolean);	/* Trusted */	boolean = read_trust(&src, device->address, GLOBAL_TRUST);	dbus_message_iter_append_dict_entry(&dict, "Trusted",			DBUS_TYPE_BOOLEAN, &boolean);	/* Connected */	if (g_slist_find_custom(adapter->active_conn, &dst,				active_conn_find_by_bdaddr))		boolean = TRUE;	else		boolean = FALSE;	dbus_message_iter_append_dict_entry(&dict, "Connected",			DBUS_TYPE_BOOLEAN, &boolean);	/* UUIDs */	uuids = g_new0(char *, g_slist_length(device->uuids) + 1);	for (i = 0, l = device->uuids; l; l = l->next, i++)		uuids[i] = l->data;	dbus_message_iter_append_dict_entry(&dict, "UUIDs",			DBUS_TYPE_ARRAY, &uuids);	g_free(uuids);	/* Adapter */	snprintf(path, sizeof(path), "%s/hci%d", "/org/bluez", dev_id);	ppath = path;	dbus_message_iter_append_dict_entry(&dict, "Adapter",			DBUS_TYPE_OBJECT_PATH, &ppath);	dbus_message_iter_close_container(&iter, &dict);	return reply;}static int remove_device_alias(const char *source, const char *destination){	char filename[PATH_MAX + 1];	create_name(filename, PATH_MAX, STORAGEDIR, source, "aliases");	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);	return textfile_del(filename, destination);}static DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,					const char *alias, void *data){	struct btd_device *device = data;	struct adapter *adapter = device->adapter;	bdaddr_t bdaddr;	int ecode;	char *str, filename[PATH_MAX + 1];	uint16_t dev_id = adapter_get_dev_id(adapter);	const gchar *source = adapter_get_address(adapter);	str2ba(device->address, &bdaddr);	/* Remove alias if empty string */	if (g_str_equal(alias, "")) {		create_name(filename, PATH_MAX, STORAGEDIR, source,				"names");		str = textfile_caseget(filename, device->address);		ecode = remove_device_alias(source, device->address);	} else {		str = g_strdup(alias);		ecode = set_device_alias(dev_id, &bdaddr, alias);	}	if (ecode < 0)		return g_dbus_create_error(msg,				ERROR_INTERFACE ".Failed",				strerror(-ecode));	dbus_connection_emit_property_changed(conn, dbus_message_get_path(msg),					DEVICE_INTERFACE, "Alias",					DBUS_TYPE_STRING, &str);	g_free(str);	return dbus_message_new_method_return(msg);}static DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,					dbus_bool_t value, void *data){	struct btd_device *device = data;	struct adapter *adapter = device->adapter;	bdaddr_t local;	const gchar *source = adapter_get_address(adapter);	str2ba(source, &local);	write_trust(&local, device->address, GLOBAL_TRUST, value);	dbus_connection_emit_property_changed(conn, dbus_message_get_path(msg),					DEVICE_INTERFACE, "Trusted",					DBUS_TYPE_BOOLEAN, &value);	return dbus_message_new_method_return(msg);}static inline DBusMessage *invalid_args(DBusMessage *msg){	return g_dbus_create_error(msg,			ERROR_INTERFACE ".InvalidArguments",			"Invalid arguments in method call");}static DBusMessage *set_property(DBusConnection *conn,				DBusMessage *msg, void *data){	DBusMessageIter iter;	DBusMessageIter sub;	const char *property;	if (!dbus_message_iter_init(msg, &iter))		return invalid_args(msg);	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)		return invalid_args(msg);	dbus_message_iter_get_basic(&iter, &property);	dbus_message_iter_next(&iter);	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)		return invalid_args(msg);	dbus_message_iter_recurse(&iter, &sub);	if (g_str_equal("Trusted", property)) {		dbus_bool_t value;		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)			return invalid_args(msg);		dbus_message_iter_get_basic(&sub, &value);		return set_trust(conn, msg, value, data);	} else if (g_str_equal("Alias", property)) {		char *alias;		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)			return invalid_args(msg);		dbus_message_iter_get_basic(&sub, &alias);		return set_alias(conn, msg, alias, data);	}	return invalid_args(msg);}static void discover_services_req_exit(void *user_data){	struct btd_device *device = user_data;	struct adapter *adapter = device->adapter;	bdaddr_t src, dst;	const gchar *source = adapter_get_address(adapter);	debug("DiscoverDevices requestor exited");	str2ba(source, &src);	str2ba(device->address, &dst);	bt_cancel_discovery(&src, &dst);}static DBusMessage *discover_services(DBusConnection *conn,					DBusMessage *msg, void *user_data){	struct btd_device *device = user_data;	const char *pattern;	int err;	if (device->discov_active)		return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",							"Discover in progress");	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,						DBUS_TYPE_INVALID) == FALSE)		goto fail;	if (strlen(pattern) == 0) {		err = device_browse(device, conn, msg, NULL);		if (err < 0)			goto fail;	} else {		uuid_t uuid;		if (bt_string2uuid(&uuid, pattern) < 0)			return invalid_args(msg);		err = device_browse(device, conn, msg, &uuid);		if (err < 0)			goto fail;	}	return NULL;fail:	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",					"Discovery Failed");}static DBusMessage *cancel_discover(DBusConnection *conn,					DBusMessage *msg, void *user_data){	struct btd_device *device = user_data;	struct adapter *adapter = device->adapter;	bdaddr_t src, dst;	const gchar *source = adapter_get_address(adapter);	if (!device->discov_active)		return g_dbus_create_error(msg,				ERROR_INTERFACE ".Failed",				"No pending discovery");	/* only the discover requestor can cancel the inquiry process */	if (!device->discov_requestor ||			strcmp(device->discov_requestor, dbus_message_get_sender(msg)))		return g_dbus_create_error(msg,				ERROR_INTERFACE ".NotAuthorized",				"Not Authorized"); 	str2ba(source, &src);	str2ba(device->address, &dst);	if (bt_cancel_discovery(&src, &dst) < 0)		return g_dbus_create_error(msg,				ERROR_INTERFACE ".Failed",				"No pending discover");	return dbus_message_new_method_return(msg);}static gboolean disconnect_timeout(gpointer user_data){	struct btd_device *device = user_data;	struct active_conn_info *ci;	GSList *l;	disconnect_cp cp;	bdaddr_t bda;	int dd;	uint16_t dev_id = adapter_get_dev_id(device->adapter);	device->disconn_timer = 0;	str2ba(device->address, &bda);	l = g_slist_find_custom(device->adapter->active_conn,				&bda, active_conn_find_by_bdaddr);	if (!l)		return FALSE;	ci = l->data;	dd = hci_open_dev(dev_id);	if (dd < 0)		goto fail;	memset(&cp, 0, sizeof(cp));	cp.handle = htobs(ci->handle);	cp.reason = HCI_OE_USER_ENDED_CONNECTION;	hci_send_cmd(dd, OGF_LINK_CTL, OCF_DISCONNECT,			DISCONNECT_CP_SIZE, &cp);	close(dd);fail:	return FALSE;}static DBusMessage *disconnect(DBusConnection *conn,					DBusMessage *msg, void *user_data){	struct btd_device *device = user_data;	GSList *l;	bdaddr_t bda;	str2ba(device->address, &bda);	l = g_slist_find_custom(device->adapter->active_conn,				&bda, active_conn_find_by_bdaddr);	if (!l)		return g_dbus_create_error(msg,				ERROR_INTERFACE ".NotConnected",				"Device is not connected");	g_dbus_emit_signal(conn, device->path,			DEVICE_INTERFACE, "DisconnectRequested",			DBUS_TYPE_INVALID);	device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER,						disconnect_timeout, device);	return dbus_message_new_method_return(msg);}static GDBusMethodTable device_methods[] = {	{ "GetProperties",	"",	"a{sv}",	get_properties	},	{ "SetProperty",	"sv",	"",		set_property	},	{ "DiscoverServices",	"s",	"a{us}",	discover_services,						G_DBUS_METHOD_FLAG_ASYNC},	{ "CancelDiscovery",	"",	"",		cancel_discover	},	{ "Disconnect",		"",	"",		disconnect	},	{ }};static GDBusSignalTable device_signals[] = {	{ "PropertyChanged",		"sv"	},	{ "DisconnectRequested",	""	},	{ }};struct btd_device *device_create(DBusConnection *conn, struct adapter *adapter,					const gchar *address){	gchar *address_up;	struct btd_device *device;	uint16_t dev_id = adapter_get_dev_id(adapter);	device = g_try_malloc0(sizeof(struct btd_device));	if (device == NULL)		return NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -