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

📄 dbus.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  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#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <stdint.h>#include <glib.h>#include <dbus/dbus.h>#ifdef NEED_DBUS_WATCH_GET_UNIX_FD#define dbus_watch_get_unix_fd dbus_watch_get_fd#endif#ifdef HAVE_DBUS_GLIB#include <dbus/dbus-glib-lowlevel.h>#endif#include "dbus.h"#include "logging.h"#define DISPATCH_TIMEOUT	0static int name_listener_initialized = 0;static GSList *name_listeners = NULL;#ifndef HAVE_DBUS_GLIBtypedef struct {	uint32_t id;	DBusTimeout *timeout;} timeout_handler_t;struct watch_info {	guint watch_id;	GIOChannel *io;	DBusConnection *conn;};struct server_info {	guint watch_id;	GIOChannel *io;	DBusServer *server;};#endifstruct disconnect_data {	void (*disconnect_cb)(void *);	void *user_data;};struct name_callback {	name_cb_t func;	void *user_data;};struct name_data {	DBusConnection *connection;	char *name;	GSList *callbacks;};static struct name_data *name_data_find(DBusConnection *connection,							const char *name){	GSList *current;	for (current = name_listeners;			current != NULL; current = current->next) {		struct name_data *data = current->data;		if (name == NULL && data->name == NULL) {			if (connection == data->connection)				return data;		} else {			if (strcmp(name, data->name) == 0)				return data;		}	}	return NULL;}static struct name_callback *name_callback_find(GSList *callbacks,					name_cb_t func, void *user_data){	GSList *current;	for (current = callbacks; current != NULL; current = current->next) {		struct name_callback *cb = current->data;		if (cb->func == func && cb->user_data == user_data)			return cb;	}	return NULL;}static void name_data_call_and_free(struct name_data *data){	GSList *l;	for (l = data->callbacks; l != NULL; l = l->next) {		struct name_callback *cb = l->data;		if (cb->func)			cb->func(data->name, cb->user_data);		g_free(cb);	}	g_slist_free(data->callbacks);	g_free(data->name);	g_free(data);}static void name_data_free(struct name_data *data){	GSList *l;	for (l = data->callbacks; l != NULL; l = l->next)		g_free(l->data);	g_slist_free(data->callbacks);	g_free(data->name);	g_free(data);}static int name_data_add(DBusConnection *connection,			const char *name, name_cb_t func, void *user_data){	int first = 1;	struct name_data *data = NULL;	struct name_callback *cb = NULL;	cb = g_new(struct name_callback, 1);	cb->func = func;	cb->user_data = user_data;	data = name_data_find(connection, name);	if (data) {		first = 0;		goto done;	}	data = g_new0(struct name_data, 1);	data->connection = connection;	data->name = g_strdup(name);	name_listeners = g_slist_append(name_listeners, data);done:	data->callbacks = g_slist_append(data->callbacks, cb);	return first;}static void name_data_remove(DBusConnection *connection,			const char *name, name_cb_t func, void *user_data){	struct name_data *data;	struct name_callback *cb = NULL;	data = name_data_find(connection, name);	if (!data)		return;	cb = name_callback_find(data->callbacks, func, user_data);	if (cb) {		data->callbacks = g_slist_remove(data->callbacks, cb);		g_free(cb);	}	if (!data->callbacks) {		name_listeners = g_slist_remove(name_listeners, data);		name_data_free(data);	}}static gboolean add_match(DBusConnection *connection, const char *name){	DBusError err;	char match_string[128];	snprintf(match_string, sizeof(match_string),			"interface=%s,member=NameOwnerChanged,arg0=%s",			DBUS_INTERFACE_DBUS, name);	dbus_error_init(&err);	dbus_bus_add_match(connection, match_string, &err);	if (dbus_error_is_set(&err)) {		error("Adding match rule \"%s\" failed: %s", match_string,				err.message);		dbus_error_free(&err);		return FALSE;	}	return TRUE;}static gboolean remove_match(DBusConnection *connection, const char *name){	DBusError err;	char match_string[128];	snprintf(match_string, sizeof(match_string),			"interface=%s,member=NameOwnerChanged,arg0=%s",			DBUS_INTERFACE_DBUS, name);	dbus_error_init(&err);	dbus_bus_remove_match(connection, match_string, &err);	if (dbus_error_is_set(&err)) {		error("Removing owner match rule for %s failed: %s",				name, err.message);		dbus_error_free(&err);		return FALSE;	}	return TRUE;}static DBusHandlerResult name_exit_filter(DBusConnection *connection,					DBusMessage *message, void *user_data){	GSList *l;	struct name_data *data;	char *name, *old, *new;	if (!dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,							"NameOwnerChanged"))		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;	if (!dbus_message_get_args(message, NULL,				DBUS_TYPE_STRING, &name,				DBUS_TYPE_STRING, &old,				DBUS_TYPE_STRING, &new,				DBUS_TYPE_INVALID)) {		error("Invalid arguments for NameOwnerChanged signal");		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;	}	/* We are not interested of service creations */	if (*new != '\0')		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;	data = name_data_find(connection, name);	if (!data) {		error("Got NameOwnerChanged signal for %s which has no listeners", name);		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;	}	for (l = data->callbacks; l != NULL; l = l->next) {		struct name_callback *cb = l->data;		cb->func(name, cb->user_data);	}	name_listeners = g_slist_remove(name_listeners, data);	name_data_free(data);	remove_match(connection, name);	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;}int name_listener_add(DBusConnection *connection, const char *name,					name_cb_t func, void *user_data){	int first;	if (!name_listener_initialized) {		if (!dbus_connection_add_filter(connection,					name_exit_filter, NULL, NULL)) {			error("dbus_connection_add_filter() failed");			return -1;		}		name_listener_initialized = 1;	}	first = name_data_add(connection, name, func, user_data);	/* The filter is already added if this is not the first callback	 * registration for the name */	if (!first)		return 0;	if (name) {		debug("name_listener_add(%s)", name);		if (!add_match(connection, name)) {			name_data_remove(connection, name, func, user_data);			return -1;		}	}	return 0;}int name_listener_remove(DBusConnection *connection, const char *name,					name_cb_t func, void *user_data){	struct name_data *data;	struct name_callback *cb;	data = name_data_find(connection, name);	if (!data) {		error("remove_name_listener: no listener for %s", name);		return -1;	}	cb = name_callback_find(data->callbacks, func, user_data);	if (!cb) {		error("No matching callback found for %s", name);		return -1;	}	data->callbacks = g_slist_remove(data->callbacks, cb);	g_free(cb);	/* Don't remove the filter if other callbacks exist */	if (data->callbacks)		return 0;	if (name) {		debug("name_listener_remove(%s)", name);		if (!remove_match(connection, name))			return -1;	}	name_data_remove(connection, name, func, user_data);	return 0;}int name_listener_indicate_disconnect(DBusConnection *connection){	struct name_data *data;	data = name_data_find(connection, NULL);	if (!data) {		error("name_listener_indicate_disconnect: no listener found");		return -1;	}	debug("name_listener_indicate_disconnect");	name_data_call_and_free(data);	return 0;}dbus_bool_t dbus_bus_get_unix_process_id(DBusConnection *conn, const char *name,						unsigned long *pid){	DBusMessage *msg, *reply;	DBusError err;	dbus_uint32_t pid_arg;	msg = dbus_message_new_method_call("org.freedesktop.DBus",						"/org/freedesktop/DBus",						"org.freedesktop.DBus",						"GetConnectionUnixProcessID");	if (!msg) {		error("Unable to allocate new message");		return FALSE;	}	if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,					DBUS_TYPE_INVALID)) {		error("Unable to append arguments to message");		dbus_message_unref(msg);		return FALSE;	}	dbus_error_init(&err);	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);	if (dbus_error_is_set(&err)) {		error("Sending GetConnectionUnixProcessID failed: %s", err.message);		dbus_error_free(&err);		dbus_message_unref(msg);		return FALSE;	}	dbus_error_init(&err);	dbus_message_get_args(reply, &err, DBUS_TYPE_UINT32, &pid_arg,					DBUS_TYPE_INVALID);	if (dbus_error_is_set(&err)) {		error("Getting GetConnectionUnixProcessID args failed: %s",				err.message);		dbus_error_free(&err);		dbus_message_unref(msg);		dbus_message_unref(reply);		return FALSE;	}	*pid = (unsigned long) pid_arg;	dbus_message_unref(msg);	dbus_message_unref(reply);	return TRUE;}static DBusHandlerResult disconnect_filter(DBusConnection *conn,						DBusMessage *msg, void *data){	struct disconnect_data *dc_data = data;

⌨️ 快捷键说明

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