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

📄 dbus-hci.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2006-2007  Nokia Corporation *  Copyright (C) 2004-2007  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 "hcid.h"#include "dbus.h"#include "textfile.h"#include "manager.h"#include "adapter.h"#include "error.h"#include "dbus-helper.h"#include "dbus-common.h"#include "dbus-error.h"#include "dbus-test.h"#include "dbus-service.h"#include "dbus-security.h"#include "dbus-hci.h"static DBusConnection *connection = NULL;void bonding_request_free(struct bonding_request_info *bonding){	if (!bonding)		return;	if (bonding->rq)		dbus_message_unref(bonding->rq);	if (bonding->conn)		dbus_connection_unref(bonding->conn);	if (bonding->io)		g_io_channel_unref(bonding->io);	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 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 dbus_bool_t send_adapter_signal(DBusConnection *conn, int devid,					const char *name, int first, ...){	va_list var_args;	dbus_bool_t ret;	char path[MAX_PATH_LENGTH];	snprintf(path, sizeof(path)-1, "%s/hci%d", BASE_PATH, devid);	va_start(var_args, first);	ret = dbus_connection_emit_signal_valist(conn, path, ADAPTER_INTERFACE,							name, first, var_args);	va_end(var_args);	return ret;}static void adapter_mode_changed(struct adapter *adapter,			const char *path, uint8_t scan_enable){	const char *mode;	adapter->scan_enable = scan_enable;	switch (scan_enable) {	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->timeout_id = g_timeout_add(adapter->discov_timeout * 1000,					discov_timeout_handler, adapter);		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->timeout_id = g_timeout_add(adapter->discov_timeout * 1000,					discov_timeout_handler, adapter);		/* ignore, this event should not be sent*/	default:		/* ignore, reserved */		return;	}	dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE,					"ModeChanged",					DBUS_TYPE_STRING, &mode,					DBUS_TYPE_INVALID);}/* * HCI D-Bus services */static void reply_pending_requests(const char *path, struct adapter *adapter){	if (!path || !adapter)		return;	/* pending bonding */	if (adapter->bonding) {		error_authentication_canceled(connection, adapter->bonding->rq);		name_listener_remove(connection,					dbus_message_get_sender(adapter->bonding->rq),					(name_cb_t) create_bond_req_exit,					adapter);		if (adapter->bonding->io_id)			g_source_remove(adapter->bonding->io_id);		g_io_channel_close(adapter->bonding->io);		bonding_request_free(adapter->bonding);		adapter->bonding = NULL;	}	/* If there is a pending reply for discovery cancel */	if (adapter->discovery_cancel) {		DBusMessage *reply;		reply = dbus_message_new_method_return(adapter->discovery_cancel);		send_message_and_unref(connection, reply);		dbus_message_unref(adapter->discovery_cancel);		adapter->discovery_cancel = NULL;	}	if (adapter->discov_active) {		/* Send discovery completed signal if there isn't name		 * to resolve */		dbus_connection_emit_signal(connection, path,						ADAPTER_INTERFACE,						"DiscoveryCompleted",						DBUS_TYPE_INVALID);		/* Cancel inquiry initiated by D-Bus client */		if (adapter->discov_requestor)			cancel_discovery(adapter);	}	if (adapter->pdiscov_active) {		/* Send periodic discovery stopped signal exit or stop		 * the device */		dbus_connection_emit_signal(connection, path,						ADAPTER_INTERFACE,						"PeriodicDiscoveryStopped",						DBUS_TYPE_INVALID);		/* Stop periodic inquiry initiated by D-Bus client */		if (adapter->pdiscov_requestor)			cancel_periodic_discovery(adapter);	}}int unregister_adapter_path(const char *path){	struct adapter *adapter = NULL;	info("Unregister path: %s", path);	dbus_connection_get_object_user_data(connection, path,						(void *) &adapter);	if (!adapter)		goto unreg;	/* check pending requests */	reply_pending_requests(path, adapter);	cancel_passkey_agent_requests(adapter->passkey_agents, path, NULL);	release_passkey_agents(adapter, NULL);	if (adapter->discov_requestor) {		name_listener_remove(connection,				adapter->discov_requestor,				(name_cb_t) discover_devices_req_exit, adapter);		g_free(adapter->discov_requestor);		adapter->discov_requestor = NULL;	}	if (adapter->pdiscov_requestor) {		name_listener_remove(connection,				adapter->pdiscov_requestor,				(name_cb_t) periodic_discover_req_exit,				adapter);		g_free(adapter->pdiscov_requestor);		adapter->pdiscov_requestor = NULL;	}	if (adapter->found_devices) {		g_slist_foreach(adapter->found_devices,				(GFunc) g_free, NULL);		g_slist_free(adapter->found_devices);		adapter->found_devices = NULL;	}	if (adapter->oor_devices) {		g_slist_foreach(adapter->oor_devices,				(GFunc) free, NULL);		g_slist_free(adapter->oor_devices);		adapter->oor_devices = NULL;	}	if (adapter->pin_reqs) {		g_slist_foreach(adapter->pin_reqs,				(GFunc) g_free, NULL);		g_slist_free(adapter->pin_reqs);		adapter->pin_reqs = NULL;	}	if (adapter->active_conn) {		g_slist_foreach(adapter->active_conn,				(GFunc) free, NULL);		g_slist_free(adapter->active_conn);		adapter->active_conn = NULL;	}	/* Check if there is a pending RemoteDeviceDisconnect request */	if (adapter->pending_dc) {		error_no_such_adapter(adapter->pending_dc->conn,				      adapter->pending_dc->msg);		g_source_remove(adapter->pending_dc->timeout_id);		dc_pending_timeout_cleanup(adapter);	}	g_free(adapter);unreg:	if (!dbus_connection_destroy_object_path(connection, path)) {		error("D-Bus failed to unregister %s object", path);		return -1;	}	return 0;}/***************************************************************** * *  Section reserved to HCI commands confirmation handling and low *  level events(eg: device attached/dettached. * *****************************************************************/int hcid_dbus_register_device(uint16_t id){	char path[MAX_PATH_LENGTH];	char *pptr = path;	struct adapter *adapter;	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	adapter = g_try_new0(struct adapter, 1);	if (!adapter) {		error("Failed to alloc memory to D-Bus path register data (%s)",				path);		return -1;	}	adapter->dev_id = id;	adapter->pdiscov_resolve_names = 1;	if (!dbus_connection_create_object_path(connection, path, adapter,						NULL)) {		error("D-Bus failed to register %s object", path);		g_free(adapter);		return -1;	}	if (!adapter_init(connection, path)) {		error("Adapter interface init failed");		goto failed;	}	if (!security_init(connection, path)) {		error("Security interface init failed");		goto failed;	}	if (!test_init(connection, path)) {		error("Test interface init failed");		goto failed;	}	/*	 * Send the adapter added signal	 */	dbus_connection_emit_signal(connection, BASE_PATH, MANAGER_INTERFACE,					"AdapterAdded",					DBUS_TYPE_STRING, &pptr,					DBUS_TYPE_INVALID);	return 0;failed:	dbus_connection_destroy_object_path(connection, path);	g_free(adapter);	return -1;}int hcid_dbus_unregister_device(uint16_t id){	char path[MAX_PATH_LENGTH];	char *pptr = path;	int ret;	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	dbus_connection_emit_signal(connection, BASE_PATH, MANAGER_INTERFACE,					"AdapterRemoved",					DBUS_TYPE_STRING, &pptr,					DBUS_TYPE_INVALID);	ret = unregister_adapter_path(path);	if (ret == 0 && get_default_adapter() == id) {		int new_default = hci_get_route(NULL);		set_default_adapter(new_default);		if (new_default >= 0) {			snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH,					new_default);			dbus_connection_emit_signal(connection, BASE_PATH,							MANAGER_INTERFACE,							"DefaultAdapterChanged",							DBUS_TYPE_STRING, &pptr,							DBUS_TYPE_INVALID);		}	}	return ret;}int hcid_dbus_start_device(uint16_t id){	char path[MAX_PATH_LENGTH];	struct hci_dev_info di;	struct adapter* adapter;	struct hci_conn_list_req *cl = NULL;	struct hci_conn_info *ci;	const char *mode;	int i, err, dd = -1, ret = -1;

⌨️ 快捷键说明

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