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

📄 adapter.c

📁 BlueZ源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * *  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#define _GNU_SOURCE#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <sys/ioctl.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/l2cap.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <glib.h>#include <dbus/dbus.h>#include <gdbus.h>#include "logging.h"#include "textfile.h"#include "hcid.h"#include "sdpd.h"#include "sdp-xml.h"#include "manager.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 "storage.h"#define NUM_ELEMENTS(table) (sizeof(table)/sizeof(const char *))#define IO_CAPABILITY_DISPLAYONLY	0x00#define IO_CAPABILITY_DISPLAYYESNO	0x01#define IO_CAPABILITY_KEYBOARDONLY	0x02#define IO_CAPABILITY_NOINPUTOUTPUT	0x03#define IO_CAPABILITY_INVALID		0xFF#define check_address(address) bachk(address)static DBusConnection *connection = NULL;static GSList *adapter_drivers = NULL;struct session_req {	struct btd_adapter	*adapter;	DBusConnection		*conn;		/* Connection reference */	DBusMessage		*msg;		/* Unreplied message ref */	char			*owner;		/* Bus name of the owner */	guint			id;		/* Listener id */	uint8_t			mode;		/* Requested mode */	int			refcount;	/* Session refcount */};struct service_auth {	service_auth_cb cb;	void *user_data;};struct btd_adapter {	uint16_t dev_id;	int up;	char *path;			/* adapter object path */	bdaddr_t bdaddr;		/* adapter Bluetooth Address */	guint discov_timeout_id;	/* discoverable timeout id */	uint32_t discov_timeout;	/* discoverable time(sec) */	guint pairable_timeout_id;	/* pairable timeout id */	uint32_t pairable_timeout;	/* pairable time(sec) */	uint8_t scan_mode;		/* scan mode: SCAN_DISABLED, SCAN_PAGE, SCAN_INQUIRY */	uint8_t mode;			/* off, connectable, discoverable, limited */	uint8_t global_mode;		/* last valid global mode */	int state;			/* standard inq, periodic inq, name resloving */	GSList *found_devices;	GSList *oor_devices;		/* out of range device list */	DBusMessage *discovery_cancel;	/* discovery cancel message request */	GSList *passkey_agents;	struct agent *agent;		/* For the new API */	GSList *active_conn;	struct bonding_request_info *bonding;	GSList *auth_reqs;		/* Received and replied HCI					   authentication requests */	GSList *devices;		/* Devices structure pointers */	GSList *mode_sessions;		/* Request Mode sessions */	GSList *disc_sessions;		/* Discovery sessions */	guint scheduler_id;		/* Scheduler handle */	struct hci_dev dev;		/* hci info */	gboolean pairable;		/* pairable state */	gboolean first_init;		/* Needed for offmode=devdown */};static void adapter_set_pairable_timeout(struct btd_adapter *adapter,					guint interval);static inline DBusMessage *invalid_args(DBusMessage *msg){	return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments",			"Invalid arguments in method call");}static inline DBusMessage *not_available(DBusMessage *msg){	return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAvailable",			"Not Available");}static inline DBusMessage *adapter_not_ready(DBusMessage *msg){	return g_dbus_create_error(msg, ERROR_INTERFACE ".NotReady",			"Adapter is not ready");}static inline DBusMessage *no_such_adapter(DBusMessage *msg){	return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchAdapter",							"No such adapter");}static inline DBusMessage *failed_strerror(DBusMessage *msg, int err){	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",							strerror(err));}static inline DBusMessage *in_progress(DBusMessage *msg, const char *str){	return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress", str);}static inline DBusMessage *not_in_progress(DBusMessage *msg, const char *str){	return g_dbus_create_error(msg, ERROR_INTERFACE ".NotInProgress", str);}static inline DBusMessage *not_authorized(DBusMessage *msg){	return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAuthorized",			"Not authorized");}static inline DBusMessage *unsupported_major_class(DBusMessage *msg){	return g_dbus_create_error(msg,			ERROR_INTERFACE ".UnsupportedMajorClass",			"Unsupported Major Class");}static DBusHandlerResult error_failed(DBusConnection *conn,					DBusMessage *msg, const char * desc){	return error_common_reply(conn, msg, ERROR_INTERFACE ".Failed", desc);}static DBusHandlerResult error_failed_errno(DBusConnection *conn,						DBusMessage *msg, int err){	const char *desc = strerror(err);	return error_failed(conn, msg, desc);}static DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn,						DBusMessage *msg, int err){	return error_common_reply(conn, msg,			ERROR_INTERFACE ".ConnectionAttemptFailed",			err > 0 ? strerror(err) : "Connection attempt failed");}static void bonding_request_free(struct bonding_request_info *bonding){	struct btd_device *device;	char address[18];	struct agent *agent;	if (!bonding)		return;	if (bonding->msg)		dbus_message_unref(bonding->msg);	if (bonding->conn)		dbus_connection_unref(bonding->conn);	if (bonding->io)		g_io_channel_unref(bonding->io);	ba2str(&bonding->bdaddr, address);	device = adapter_find_device(bonding->adapter, address);	agent = device_get_agent(device);	if (device && agent) {		agent_destroy(agent, FALSE);		device_set_agent(device, NULL);	}	g_free(bonding);}static int active_conn_find_by_bdaddr(const void *data, const void *user_data){	const struct active_conn_info *con = data;	const bdaddr_t *bdaddr = user_data;	return bacmp(&con->bdaddr, bdaddr);}static int active_conn_find_by_handle(const void *data, const void *user_data){	const struct active_conn_info *dev = data;	const uint16_t *handle = user_data;	if (dev->handle == *handle)		return 0;	return -1;}static void send_out_of_range(const char *path, GSList *l){	while (l) {		const char *peer_addr = l->data;		g_dbus_emit_signal(connection, path,				ADAPTER_INTERFACE, "DeviceDisappeared",				DBUS_TYPE_STRING, &peer_addr,				DBUS_TYPE_INVALID);		l = l->next;	}}static int found_device_cmp(const struct remote_dev_info *d1,			const struct remote_dev_info *d2){	int ret;	if (bacmp(&d2->bdaddr, BDADDR_ANY)) {		ret = bacmp(&d1->bdaddr, &d2->bdaddr);		if (ret)			return ret;	}	if (d2->name_status != NAME_ANY) {		ret = (d1->name_status - d2->name_status);		if (ret)			return ret;	}	return 0;}static int auth_req_cmp(const void *p1, const void *p2){	const struct pending_auth_info *pb1 = p1;	const bdaddr_t *bda = p2;	return bda ? bacmp(&pb1->bdaddr, bda) : -1;}struct pending_auth_info *adapter_find_auth_request(struct btd_adapter *adapter,							bdaddr_t *dba){	GSList *l;	l = g_slist_find_custom(adapter->auth_reqs, dba, auth_req_cmp);	if (l)		return l->data;	return NULL;}void adapter_remove_auth_request(struct btd_adapter *adapter, bdaddr_t *dba){	GSList *l;	struct pending_auth_info *auth;	l = g_slist_find_custom(adapter->auth_reqs, dba, auth_req_cmp);	if (!l)		return;	auth = l->data;	adapter->auth_reqs = g_slist_remove(adapter->auth_reqs, auth);	g_free(auth);}struct pending_auth_info *adapter_new_auth_request(struct btd_adapter *adapter,							bdaddr_t *dba,							auth_type_t type){	struct pending_auth_info *info;	debug("hcid_dbus_new_auth_request");	info = g_new0(struct pending_auth_info, 1);	bacpy(&info->bdaddr, dba);	info->type = type;	adapter->auth_reqs = g_slist_append(adapter->auth_reqs, info);	if (adapter->bonding && !bacmp(dba, &adapter->bonding->bdaddr))		adapter->bonding->auth_active = 1;	return info;}static void dev_info_free(struct remote_dev_info *dev){	g_free(dev->alias);	g_free(dev);}int pending_remote_name_cancel(struct btd_adapter *adapter){	struct remote_dev_info *dev, match;	GSList *l;	int dd, err = 0;	/* find the pending remote name request */	memset(&match, 0, sizeof(struct remote_dev_info));	bacpy(&match.bdaddr, BDADDR_ANY);	match.name_status = NAME_REQUESTED;	l = g_slist_find_custom(adapter->found_devices, &match,			(GCompareFunc) found_device_cmp);	if (!l) /* no pending request */		return 0;	dd = hci_open_dev(adapter->dev_id);	if (dd < 0)		return -ENODEV;	dev = l->data;	if (hci_read_remote_name_cancel(dd, &dev->bdaddr,					HCI_REQ_TIMEOUT) < 0) {		error("Remote name cancel failed: %s(%d)", strerror(errno), errno);		err = -errno;	}	/* free discovered devices list */	g_slist_foreach(adapter->found_devices, (GFunc) dev_info_free, NULL);	g_slist_free(adapter->found_devices);	adapter->found_devices = NULL;	hci_close_dev(dd);	return err;}static int auth_info_agent_cmp(const void *a, const void *b){	const struct pending_auth_info *auth = a;	const struct agent *agent = b;	if (auth->agent == agent)		return 0;	return -1;}static void device_agent_removed(struct agent *agent, void *user_data){	struct btd_device *device = user_data;	struct pending_auth_info *auth;	GSList *l;	struct btd_adapter *adapter;	adapter = device_get_adapter(device);	device_set_agent(device, NULL);	l = g_slist_find_custom(adapter->auth_reqs, agent,					auth_info_agent_cmp);	if (!l)		return;	auth = l->data;	auth->agent = NULL;}static struct bonding_request_info *bonding_request_new(DBusConnection *conn,							DBusMessage *msg,							struct btd_adapter *adapter,							const char *address,							const char *agent_path,							uint8_t capability){	struct bonding_request_info *bonding;	struct btd_device *device;	const char *name = dbus_message_get_sender(msg);	struct agent *agent;	char addr[18];	bdaddr_t bdaddr;	debug("bonding_request_new(%s)", address);	device = adapter_get_device(conn, adapter, address);	if (!device)		return NULL;	device_get_address(device, &bdaddr);	ba2str(&bdaddr, addr);	agent = agent_create(adapter, name, agent_path,					capability,					device_agent_removed,					device);	device_set_agent(device, agent);	debug("Temporary agent registered for hci%d/%s at %s:%s",			adapter->dev_id, addr, name,			agent_path);	bonding = g_new0(struct bonding_request_info, 1);	bonding->conn = dbus_connection_ref(conn);	bonding->msg = dbus_message_ref(msg);	bonding->adapter = adapter;	str2ba(address, &bonding->bdaddr);	return bonding;}static int set_limited_discoverable(int dd, const uint8_t *cls, gboolean limited){	uint32_t dev_class;	int num = (limited ? 2 : 1);	uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e };	/*	 * 1: giac	 * 2: giac + liac	 */	if (hci_write_current_iac_lap(dd, num, lap, HCI_REQ_TIMEOUT) < 0) {		int err = -errno;		error("Can't write current IAC LAP: %s(%d)",				strerror(err), err);		return err;	}	if (limited) {		if (cls[1] & 0x20)			return 0; /* Already limited */		dev_class = (cls[2] << 16) | ((cls[1] | 0x20) << 8) | cls[0];	} else {		if (!(cls[1] & 0x20))			return 0; /* Already clear */		dev_class = (cls[2] << 16) | ((cls[1] & 0xdf) << 8) | cls[0];	}	if (hci_write_class_of_dev(dd, dev_class, HCI_REQ_TIMEOUT) < 0) {		int err = -errno;		error("Can't write class of device: %s (%d)",							strerror(err), err);		return err;	}	return 0;}static const char *mode2str(uint8_t mode){	switch(mode) {	case MODE_OFF:		return "off";	case MODE_CONNECTABLE:		return "connectable";	case MODE_DISCOVERABLE:	case MODE_LIMITED:		return "discoverable";	default:		return "unknown";	}}static uint8_t get_mode(const bdaddr_t *bdaddr, const char *mode){	if (strcasecmp("off", mode) == 0)		return MODE_OFF;	else if (strcasecmp("connectable", mode) == 0)		return MODE_CONNECTABLE;	else if (strcasecmp("discoverable", mode) == 0)		return MODE_DISCOVERABLE;	else if (strcasecmp("limited", mode) == 0)		return MODE_LIMITED;	else if (strcasecmp("on", mode) == 0) {		char onmode[14], srcaddr[18];		ba2str(bdaddr, srcaddr);		if (read_on_mode(srcaddr, onmode, sizeof(onmode)) < 0)			return MODE_CONNECTABLE;		return get_mode(bdaddr, onmode);	} else		return MODE_UNKNOWN;}static void adapter_remove_discov_timeout(struct btd_adapter *adapter){	if (!adapter)		return;	if(adapter->discov_timeout_id == 0)		return;	g_source_remove(adapter->discov_timeout_id);	adapter->discov_timeout_id = 0;}static gboolean discov_timeout_handler(gpointer user_data){	struct btd_adapter *adapter = user_data;

⌨️ 快捷键说明

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