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

📄 dbus-hci.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * *  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 <unistd.h>#include <stdlib.h>#include <string.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/sdp.h>#include <glib.h>#include <dbus/dbus.h>#include <gdbus.h>#include "hcid.h"#include "textfile.h"#include "manager.h"#include "adapter.h"#include "device.h"#include "error.h"#include "glib-helper.h"#include "dbus-common.h"#include "agent.h"#include "dbus-hci.h"static DBusConnection *connection = NULL;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);}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;}int dev_rssi_cmp(struct remote_dev_info *d1, struct remote_dev_info *d2){	int rssi1, rssi2;	rssi1 = d1->rssi < 0 ? -d1->rssi : d1->rssi;	rssi2 = d2->rssi < 0 ? -d2->rssi : d2->rssi;	return rssi1 - rssi2;}int found_device_add(GSList **list, bdaddr_t *bdaddr, int8_t rssi,			name_status_t name_status){	struct remote_dev_info *dev, match;	GSList *l;	memset(&match, 0, sizeof(struct remote_dev_info));	bacpy(&match.bdaddr, bdaddr);	match.name_status = NAME_ANY;	/* ignore repeated entries */	l = g_slist_find_custom(*list, &match, (GCompareFunc) found_device_cmp);	if (l) {		/* device found, update the attributes */		dev = l->data;		if (rssi != 0)			dev->rssi = rssi;		 /* Get remote name can be received while inquiring.		  * Keep in mind that multiple inquiry result events can		  * be received from the same remote device.		  */		if (name_status != NAME_NOT_REQUIRED)			dev->name_status = name_status;		*list = g_slist_sort(*list, (GCompareFunc) dev_rssi_cmp);		return -EALREADY;	}	dev = g_new0(struct remote_dev_info, 1);	bacpy(&dev->bdaddr, bdaddr);	dev->rssi = rssi;	dev->name_status = name_status;	*list = g_slist_insert_sorted(*list, dev, (GCompareFunc) dev_rssi_cmp);	return 0;}static int found_device_remove(GSList **list, bdaddr_t *bdaddr){	struct remote_dev_info *dev, match;	GSList *l;	memset(&match, 0, sizeof(struct remote_dev_info));	bacpy(&match.bdaddr, bdaddr);	l = g_slist_find_custom(*list, &match, (GCompareFunc) found_device_cmp);	if (!l)		return -1;	dev = l->data;	*list = g_slist_remove(*list, dev);	g_free(dev);	return 0;}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 int active_conn_append(GSList **list, bdaddr_t *bdaddr,				uint16_t handle){	struct active_conn_info *dev;	dev = g_new0(struct active_conn_info, 1);	bacpy(&dev->bdaddr, bdaddr);	dev->handle = handle;	*list = g_slist_append(*list, dev);	return 0;}DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status){	switch (status) {	case 0x00: /* success */		return dbus_message_new_method_return(msg);	case 0x04: /* page timeout */	case 0x08: /* connection timeout */	case 0x10: /* connection accept timeout */	case 0x22: /* LMP response timeout */	case 0x28: /* instant passed - is this a timeout? */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationTimeout",					"Authentication Timeout");	case 0x17: /* too frequent pairing attempts */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".RepeatedAttempts",					"Repeated Attempts");	case 0x06:	case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationRejected",					"Authentication Rejected");	case 0x07: /* memory capacity */	case 0x09: /* connection limit */	case 0x0a: /* synchronous connection limit */	case 0x0d: /* limited resources */	case 0x13: /* user ended the connection */	case 0x14: /* terminated due to low resources */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationCanceled",					"Authentication Canceled");	case 0x05: /* authentication failure */	case 0x0E: /* rejected due to security reasons - is this auth failure? */	case 0x25: /* encryption mode not acceptable - is this auth failure? */	case 0x26: /* link key cannot be changed - is this auth failure? */	case 0x29: /* pairing with unit key unsupported - is this auth failure? */	case 0x2f: /* insufficient security - is this auth failure? */	default:		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationFailed",					"Authentication Failed");	}}static void adapter_mode_changed(struct adapter *adapter, uint8_t scan_mode){	const char *mode;	const gchar *path = adapter_get_path(adapter);	adapter_set_scan_mode(adapter, scan_mode);	switch (scan_mode) {	case SCAN_DISABLED:		mode = "off";		adapter->mode = MODE_OFF;		break;	case SCAN_PAGE:		mode = "connectable";		adapter->mode = MODE_CONNECTABLE;		break;	case (SCAN_PAGE | SCAN_INQUIRY):		if (adapter->discov_timeout != 0)			adapter_set_discov_timeout(adapter, adapter->discov_timeout * 1000);		if (adapter->mode == MODE_LIMITED) {			mode = "limited";		} else {			adapter->mode = MODE_DISCOVERABLE;			mode = "discoverable";		}		break;	case SCAN_INQUIRY:		/* Address the scenario where another app changed the scan mode */		if (adapter->discov_timeout != 0)			adapter_set_discov_timeout(adapter, adapter->discov_timeout * 1000);		/* ignore, this event should not be sent*/	default:		/* ignore, reserved */		return;	}	dbus_connection_emit_property_changed(connection, path,					ADAPTER_INTERFACE, "Mode",					DBUS_TYPE_STRING, &mode);}/***************************************************************** * *  Section reserved to HCI commands confirmation handling and low *  level events(eg: device attached/dettached. * *****************************************************************/static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,			struct btd_device *device){	struct adapter *adapter = device_get_adapter(device);	pin_code_reply_cp pr;	bdaddr_t sba, dba;	size_t len;	int dev;	struct pending_auth_info *auth;	const gchar *destination = device_get_address(device);	uint16_t dev_id = adapter_get_dev_id(adapter);	const gchar *source = adapter_get_address(adapter);	/* No need to reply anything if the authentication already failed */	if (adapter->bonding && adapter->bonding->hci_status)		return;	dev = hci_open_dev(dev_id);	if (dev < 0) {		error("hci_open_dev(%d): %s (%d)", dev_id,				strerror(errno), errno);		return;	}	str2ba(source, &sba);	str2ba(destination, &dba);	auth = adapter_find_auth_request(adapter, &dba);	if (err) {		hci_send_cmd(dev, OGF_LINK_CTL,				OCF_PIN_CODE_NEG_REPLY, 6, &dba);		goto done;	}	len = strlen(pincode);	set_pin_length(&sba, len);	memset(&pr, 0, sizeof(pr));	bacpy(&pr.bdaddr, &dba);	memcpy(pr.pin_code, pincode, len);	pr.pin_len = len;	hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr);done:	if (auth) {		auth->replied = TRUE;		auth->agent = NULL;	}	hci_close_dev(dev);}int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci){	char addr[18];	struct adapter *adapter;	struct btd_device *device;	struct agent *agent = NULL;	int ret;	adapter = manager_find_adapter(sba);	if (!adapter) {		error("No matching adapter found");		return -1;	}	ba2str(&ci->bdaddr, addr);	device = adapter_find_device(adapter, addr);	if (device)		agent = device_get_agent(device);	if (!agent)		agent = adapter->agent;	if (!agent)		return -EPERM;	if (!device) {		device = adapter_create_device(connection, adapter, addr);		if (!device)			return -ENODEV;	}	ret = agent_request_pincode(agent, device,					(agent_pincode_cb) pincode_cb,					device);	if (ret == 0) {		struct pending_auth_info *auth;		auth = adapter_new_auth_request(adapter, &ci->bdaddr,						AUTH_TYPE_PINCODE);		auth->agent = agent;	}	return ret;}static void confirm_cb(struct agent *agent, DBusError *err, void *user_data){	struct btd_device *device = user_data;	struct adapter *adapter = device_get_adapter(device);	user_confirm_reply_cp cp;	int dd;	struct pending_auth_info *auth;	const gchar *destination = device_get_address(device);	uint16_t dev_id = adapter_get_dev_id(adapter);	/* No need to reply anything if the authentication already failed */	if (adapter->bonding && adapter->bonding->hci_status)		return;	dd = hci_open_dev(dev_id);	if (dd < 0) {		error("Unable to open hci%d", dev_id);		return;	}	memset(&cp, 0, sizeof(cp));	str2ba(destination, &cp.bdaddr);	auth = adapter_find_auth_request(adapter, &cp.bdaddr);	if (err)		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY,					USER_CONFIRM_REPLY_CP_SIZE, &cp);	else		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_REPLY,					USER_CONFIRM_REPLY_CP_SIZE, &cp);	if (auth) {		auth->replied = TRUE;		auth->agent = FALSE;	}	hci_close_dev(dd);}static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,			void *user_data){	struct btd_device *device = user_data;	struct adapter *adapter = device_get_adapter(device);	user_passkey_reply_cp cp;	bdaddr_t dba;	int dd;	struct pending_auth_info *auth;	const gchar *destination = device_get_address(device);	uint16_t dev_id = adapter_get_dev_id(adapter);	/* No need to reply anything if the authentication already failed */	if (adapter->bonding && adapter->bonding->hci_status)		return;	dd = hci_open_dev(dev_id);	if (dd < 0) {		error("Unable to open hci%d", dev_id);		return;	}	str2ba(destination, &dba);	memset(&cp, 0, sizeof(cp));	bacpy(&cp.bdaddr, &dba);	cp.passkey = passkey;	auth = adapter_find_auth_request(adapter, &dba);	if (err)		hci_send_cmd(dd, OGF_LINK_CTL,				OCF_USER_PASSKEY_NEG_REPLY, 6, &dba);	else		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_PASSKEY_REPLY,					USER_PASSKEY_REPLY_CP_SIZE, &cp);	if (auth) {		auth->replied = TRUE;		auth->agent = NULL;	}	hci_close_dev(dd);}static int get_auth_requirements(bdaddr_t *local, bdaddr_t *remote,							uint8_t *auth){	struct hci_auth_info_req req;	char addr[18];	int err, dd, dev_id;	ba2str(local, addr);	dev_id = hci_devid(addr);

⌨️ 快捷键说明

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