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

📄 adapter.c

📁 这是Linux环境下的蓝牙源代码
💻 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 <time.h>#include <sys/param.h>#include <sys/ioctl.h>#include <sys/socket.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 "hcid.h"#include "sdpd.h"#include "adapter.h"#include "device.h"#include "textfile.h"#include "oui.h"#include "dbus-common.h"#include "dbus-hci.h"#include "dbus-database.h"#include "error.h"#include "glib-helper.h"#include "logging.h"#include "agent.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		0xFFstatic DBusConnection *connection = NULL;struct record_list {  sdp_list_t *recs;  const gchar *addr;};struct mode_req {	struct adapter	*adapter;	DBusConnection	*conn;		/* Connection reference */	DBusMessage	*msg;		/* Message reference */	uint8_t		mode;		/* Requested mode */	guint		id;		/* Listener id */};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 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;}void adapter_auth_request_replied(struct 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;	auth->replied = TRUE;}struct pending_auth_info *adapter_find_auth_request(struct 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 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 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;}int pending_remote_name_cancel(struct 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, 1000) < 0) {		error("Remote name cancel failed: %s(%d)", strerror(errno), errno);		err = -errno;	}	/* free discovered devices list */	g_slist_foreach(adapter->found_devices, (GFunc) g_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 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 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);	const gchar *destination;	struct agent *agent;	debug("bonding_request_new(%s)", address);	device = adapter_get_device(conn, adapter, address);	if (!device)		return NULL;	destination = device_get_address(device);	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, destination, 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;}const char *mode2str(uint8_t mode){	switch(mode) {	case MODE_OFF:		return "off";	case MODE_CONNECTABLE:		return "connectable";	case MODE_DISCOVERABLE:		return "discoverable";	case MODE_LIMITED:		return "limited";	default:		return "unknown";	}}static uint8_t on_mode(const char *addr){	char mode[14];	bdaddr_t sba;	str2ba(addr, &sba);	if (read_on_mode(&sba, mode, sizeof(mode)) < 0)		return MODE_CONNECTABLE;	return str2mode(addr, mode);}uint8_t str2mode(const char *addr, 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)		return on_mode(addr);	else		return MODE_UNKNOWN;}static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg,				uint8_t new_mode, void *data){	struct adapter *adapter = data;	uint8_t scan_enable;	uint8_t current_scan = adapter->scan_mode;	bdaddr_t local;	gboolean limited;	int err, dd;	const char *mode;	switch(new_mode) {	case MODE_OFF:		scan_enable = SCAN_DISABLED;		break;	case MODE_CONNECTABLE:		scan_enable = SCAN_PAGE;		break;	case MODE_DISCOVERABLE:	case MODE_LIMITED:		scan_enable = (SCAN_PAGE | SCAN_INQUIRY);		break;	default:		return invalid_args(msg);	}	/* Do reverse resolution in case of "on" mode */	mode = mode2str(new_mode);	dd = hci_open_dev(adapter->dev_id);	if (dd < 0)		return no_such_adapter(msg);	if (!adapter->up &&			(hcid.offmode == HCID_OFFMODE_NOSCAN ||			 (hcid.offmode == HCID_OFFMODE_DEVDOWN &&			  scan_enable != SCAN_DISABLED))) {		/* Start HCI device */		if (ioctl(dd, HCIDEVUP, adapter->dev_id) == 0)			goto done; /* on success */		if (errno != EALREADY) {			err = errno;			error("Can't init device hci%d: %s (%d)\n",				adapter->dev_id, strerror(errno), errno);			hci_close_dev(dd);			return failed_strerror(msg, err);		}	}	if (adapter->up && scan_enable == SCAN_DISABLED &&			hcid.offmode == HCID_OFFMODE_DEVDOWN) {		if (ioctl(dd, HCIDEVDOWN, adapter->dev_id) < 0) {			hci_close_dev(dd);			return failed_strerror(msg, errno);		}		goto done;	}	limited = (new_mode == MODE_LIMITED ? TRUE : FALSE);	err = set_limited_discoverable(dd, adapter->dev.class, limited);	if (err < 0) {		hci_close_dev(dd);		return failed_strerror(msg, -err);	}	if (current_scan != scan_enable) {		struct hci_request rq;		uint8_t status = 0;		memset(&rq, 0, sizeof(rq));		rq.ogf    = OGF_HOST_CTL;		rq.ocf    = OCF_WRITE_SCAN_ENABLE;		rq.cparam = &scan_enable;		rq.clen   = sizeof(scan_enable);		rq.rparam = &status;		rq.rlen   = sizeof(status);		rq.event = EVT_CMD_COMPLETE;		if (hci_send_req(dd, &rq, 1000) < 0) {			err = errno;			error("Sending write scan enable command failed: %s (%d)",					strerror(errno), errno);			hci_close_dev(dd);			return failed_strerror(msg, err);		}		if (status) {			error("Setting scan enable failed with status 0x%02x",					status);			hci_close_dev(dd);			return failed_strerror(msg, bt_error(status));		}	} else {		/* discoverable or limited */		if ((scan_enable & SCAN_INQUIRY) && (new_mode != adapter->mode)) {			if (adapter->discov_timeout_id)				g_source_remove(adapter->discov_timeout_id);			if (!adapter->sessions && !adapter->discov_timeout)				adapter->discov_timeout_id = g_timeout_add(adapter->discov_timeout * 1000,						discov_timeout_handler, adapter);		}	}done:	str2ba(adapter->address, &local);	write_device_mode(&local, mode);	hci_close_dev(dd);	adapter->mode = new_mode;	return dbus_message_new_method_return(msg);}gint find_session(struct mode_req *req, DBusMessage *msg){	const char *name = dbus_message_get_sender(req->msg);	const char *sender = dbus_message_get_sender(msg);	return strcmp(name, sender);}static void confirm_mode_cb(struct agent *agent, DBusError *err, void *data){	struct mode_req *req = data;	DBusMessage *reply;	if (err && dbus_error_is_set(err)) {		reply = dbus_message_new_error(req->msg, err->name, err->message);		dbus_connection_send(req->conn, reply, NULL);		dbus_message_unref(reply);		goto cleanup;	}	reply = set_mode(req->conn, req->msg, req->mode, req->adapter);	dbus_connection_send(req->conn, reply, NULL);	dbus_message_unref(reply);	if (!g_slist_find_custom(req->adapter->sessions, req->msg,			(GCompareFunc) find_session))		goto cleanup;	return;cleanup:	dbus_message_unref(req->msg);	if (req->id)		g_dbus_remove_watch(req->conn, req->id);	dbus_connection_unref(req->conn);	g_free(req);}static DBusMessage *confirm_mode(DBusConnection *conn, DBusMessage *msg,

⌨️ 快捷键说明

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