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

📄 agent.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2006-2008  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 <sys/socket.h>#include <sys/ioctl.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 "dbus-common.h"#include "error.h"#include "adapter.h"#include "dbus-hci.h"#include "device.h"#include "agent.h"#define REQUEST_TIMEOUT (60 * 1000)		/* 60 seconds */#define AGENT_TIMEOUT (10 * 60 * 1000)		/* 10 minutes */typedef enum {	AGENT_REQUEST_PASSKEY,	AGENT_REQUEST_CONFIRMATION,	AGENT_REQUEST_PINCODE,	AGENT_REQUEST_AUTHORIZE,	AGENT_REQUEST_CONFIRM_MODE} agent_request_type_t;struct agent {	struct adapter *adapter;	char *name;	char *path;	uint8_t capability;	struct agent_request *request;	int exited;	agent_remove_cb remove_cb;	void *remove_cb_data;	guint listener_id;};struct agent_request {	agent_request_type_t type;	struct agent *agent;	DBusMessage *msg;	DBusPendingCall *call;	void *cb;	void *user_data;};static DBusConnection *connection = NULL;static int request_fallback(struct agent_request *req,				DBusPendingCallNotifyFunction function);static void agent_release(struct agent *agent){	DBusMessage *message;	debug("Releasing agent %s, %s", agent->name, agent->path);	if (agent->request)		agent_cancel(agent);	message = dbus_message_new_method_call(agent->name, agent->path,			"org.bluez.Agent", "Release");	if (message == NULL) {		error("Couldn't allocate D-Bus message");		return;	}	dbus_message_set_no_reply(message, TRUE);	dbus_connection_send(connection, message, NULL);	dbus_message_unref(message);}static int send_cancel_request(struct agent_request *req){	DBusMessage *message;	message = dbus_message_new_method_call(req->agent->name, req->agent->path,						"org.bluez.Agent", "Cancel");	if (message == NULL) {		error("Couldn't allocate D-Bus message");		return -ENOMEM;	}	dbus_message_set_no_reply(message, TRUE);	dbus_connection_send(connection, message, NULL);	dbus_message_unref(message);	return 0;}static void agent_request_free(struct agent_request *req){	if (req->msg)		dbus_message_unref(req->msg);	if (req->call)		dbus_pending_call_unref(req->call);	if (req->agent && req->agent->request)		req->agent->request = NULL;	g_free(req);}static void agent_exited(void *user_data){	struct agent *agent = user_data;	debug("Agent exited without calling Unregister");	agent_destroy(agent, TRUE);}static void agent_free(struct agent *agent){	if (!agent)		return;	if (agent->remove_cb)		agent->remove_cb(agent, agent->remove_cb_data);	if (agent->request) {		DBusError err;		agent_pincode_cb pincode_cb;		agent_cb cb;		dbus_error_init(&err);		dbus_set_error_const(&err, "org.bluez.Error.Failed", "Canceled");		switch (agent->request->type) {		case AGENT_REQUEST_PINCODE:			pincode_cb = agent->request->cb;			pincode_cb(agent, &err, NULL, agent->request->user_data);			break;		default:			cb = agent->request->cb;			cb(agent, &err, agent->request->user_data);		}		dbus_error_free(&err);		agent_cancel(agent);	}	if (!agent->exited) {		g_dbus_remove_watch(connection, agent->listener_id);		agent_release(agent);	}	g_free(agent->name);	g_free(agent->path);	g_free(agent);}struct agent *agent_create(struct adapter *adapter, const char *name,				const char *path, uint8_t capability,				agent_remove_cb cb, void *remove_cb_data){	struct agent *agent;	if (adapter->agent && g_str_equal(adapter->agent->name, name))		return NULL;	agent = g_new0(struct agent, 1);	agent->adapter = adapter;	agent->name = g_strdup(name);	agent->path = g_strdup(path);	agent->capability = capability;	agent->remove_cb = cb;	agent->remove_cb_data = remove_cb_data;	agent->listener_id = g_dbus_add_disconnect_watch(connection, name,							agent_exited, agent,							NULL);	return agent;}int agent_destroy(struct agent *agent, gboolean exited){	agent->exited = exited;	agent_free(agent);	return 0;}static struct agent_request *agent_request_new(struct agent *agent,						agent_request_type_t type,						void *cb,						void *user_data){	struct agent_request *req;	req = g_new0(struct agent_request, 1);	req->agent = agent;	req->type = type;	req->cb = cb;	req->user_data = user_data;	return req;}int agent_cancel(struct agent *agent){	if (!agent->request)		return -EINVAL;	if (agent->request->call)		dbus_pending_call_cancel(agent->request->call);	if (!agent->exited)		send_cancel_request(agent->request);	agent_request_free(agent->request);	agent->request = NULL;	return 0;}static void simple_agent_reply(DBusPendingCall *call, void *user_data){	struct agent_request *req = user_data;	struct agent *agent = req->agent;	DBusMessage *message;	DBusError err;	agent_cb cb = req->cb;	/* steal_reply will always return non-NULL since the callback	 * is only called after a reply has been received */	message = dbus_pending_call_steal_reply(call);	dbus_error_init(&err);	if (dbus_set_error_from_message(&err, message)) {		if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||				g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&				request_fallback(req, simple_agent_reply) == 0) {			dbus_error_free(&err);			return;		}		error("Agent replied with an error: %s, %s",				err.name, err.message);		cb(agent, &err, req->user_data);		dbus_error_free(&err);		goto done;	}	dbus_error_init(&err);	if (!dbus_message_get_args(message, &err, DBUS_TYPE_INVALID)) {		error("Wrong reply signature: %s", err.message);		cb(agent, &err, req->user_data);		dbus_error_free(&err);		goto done;	}	cb(agent, NULL, req->user_data);done:	dbus_message_unref(message);	agent->request = NULL;	agent_request_free(req);}static int agent_call_authorize(struct agent_request *req,				const char *device_path,				const char *uuid){	struct agent *agent = req->agent;	req->msg = dbus_message_new_method_call(agent->name, agent->path,				"org.bluez.Agent", "Authorize");	if (!req->msg) {		error("Couldn't allocate D-Bus message");		return -ENOMEM;	}	dbus_message_append_args(req->msg,				DBUS_TYPE_OBJECT_PATH, &device_path,				DBUS_TYPE_STRING, &uuid,				DBUS_TYPE_INVALID);	if (dbus_connection_send_with_reply(connection, req->msg,					&req->call, REQUEST_TIMEOUT) == FALSE) {		error("D-Bus send failed");		return -EIO;	}	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);	return 0;}int agent_authorize(struct agent *agent,			const char *path,			const char *uuid,			agent_cb cb,			void *user_data){	struct agent_request *req;	int err;	if (agent->request)		return -EBUSY;	req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZE, cb, user_data);	err = agent_call_authorize(req, path, uuid);	if (err < 0) {		agent_request_free(req);		return DBUS_HANDLER_RESULT_NEED_MEMORY;	}	agent->request = req;	debug("authorize request was sent for %s", path);	return 0;}static void pincode_reply(DBusPendingCall *call, void *user_data){	struct agent_request *req = user_data;	struct agent *agent = req->agent;	struct adapter *adapter = agent->adapter;	agent_pincode_cb cb = req->cb;	DBusMessage *message;	DBusError err;	bdaddr_t sba;	size_t len;	char *pin;	const gchar *source = adapter_get_address(adapter);	/* steal_reply will always return non-NULL since the callback	 * is only called after a reply has been received */	message = dbus_pending_call_steal_reply(call);	dbus_error_init(&err);	if (dbus_set_error_from_message(&err, message)) {		if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||				g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&				request_fallback(req, pincode_reply) == 0) {			dbus_error_free(&err);			return;		}		error("Agent replied with an error: %s, %s",				err.name, err.message);		cb(agent, &err, NULL, req->user_data);		dbus_error_free(&err);		goto done;

⌨️ 快捷键说明

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