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

📄 dbus-test.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  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#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <bluetooth/bluetooth.h>#include <bluetooth/l2cap.h>#include <bluetooth/sdp.h>#include <glib.h>#include <dbus/dbus.h>#include "dbus.h"#include "dbus-helper.h"#include "hcid.h"#include "dbus-common.h"#include "adapter.h"#include "dbus-hci.h"#include "dbus-error.h"#include "error.h"#include "dbus-test.h"#define L2INFO_TIMEOUT (2 * 1000)enum {	AUDIT_STATE_MTU = 0,	AUDIT_STATE_FEATURES};struct audit {	bdaddr_t peer;	bdaddr_t local;	/* We need to store the path instead of a pointer to the data	 * because by the time the audit is processed the adapter	 * might have gotten removed. Storing only the path allows us to	 * detect this scenario */	char adapter_path[PATH_MAX];	char *requestor;	DBusConnection *conn;	GIOChannel *io;	guint io_id;	guint timeout;	int state;	uint16_t mtu_result;	uint16_t mtu;	uint16_t mask_result;	uint32_t mask;};static GSList *audits = NULL;static gboolean l2raw_connect_complete(GIOChannel *io, GIOCondition cond,					struct audit *audit);static struct audit *audit_new(DBusConnection *conn, DBusMessage *msg,				bdaddr_t *peer, bdaddr_t *local){	struct audit *audit;	const char *path;	const char *requestor;	path = dbus_message_get_path(msg);	requestor = dbus_message_get_sender(msg);	audit = g_new0(struct audit, 1);	audit->requestor = g_strdup(requestor);	bacpy(&audit->peer, peer);	bacpy(&audit->local, local);	strncpy(audit->adapter_path, path, sizeof(audit->adapter_path) - 1);	audit->conn = dbus_connection_ref(conn);	return audit;}static void audit_free(struct audit *audit){	g_free(audit->requestor);	dbus_connection_unref(audit->conn);	g_free(audit);}static void send_audit_status(struct audit *audit, const char *name){	char addr[18], *addr_ptr = addr;	ba2str(&audit->peer, addr);	dbus_connection_emit_signal(audit->conn, audit->adapter_path,					TEST_INTERFACE, name,					DBUS_TYPE_STRING, &addr_ptr,					DBUS_TYPE_INVALID);}static void audit_requestor_exited(const char *name, struct audit *audit){	debug("AuditRemoteDevice requestor %s exited", name);	audits = g_slist_remove(audits, audit);	if (audit->io) {		struct adapter *adapter = NULL;		send_audit_status(audit, "AuditRemoteDeviceComplete");		dbus_connection_get_object_user_data(audit->conn,							audit->adapter_path,							(void *) &adapter);		if (adapter)			bacpy(&adapter->agents_disabled, BDADDR_ANY);		g_io_channel_close(audit->io);	}	if (audit->timeout)		g_source_remove(audit->timeout);	audit_free(audit);}int audit_addr_cmp(const void *a, const void *b){	const struct audit *audit = a;	const bdaddr_t *addr = b;	return bacmp(&audit->peer, addr);}static gboolean audit_in_progress(void){	GSList *l;	for (l = audits; l != NULL; l = l->next) {		struct audit *audit = l->data;		if (audit->io)			return TRUE;	}	return FALSE;}static gboolean l2raw_input_timer(struct audit *audit){	error("l2raw_input_timer: Timed out while waiting for input");	send_audit_status(audit, "AuditRemoteDeviceComplete");	g_io_channel_close(audit->io);	audits = g_slist_remove(audits, audit);	name_listener_remove(audit->conn, audit->requestor,				(name_cb_t) audit_requestor_exited, audit);	audit_free(audit);	return FALSE;}static void handle_mtu_response(struct audit *audit, const l2cap_info_rsp *rsp){	audit->mtu_result = btohs(rsp->result);	switch (audit->mtu_result) {	case 0x0000:		audit->mtu = btohs(bt_get_unaligned((uint16_t *) rsp->data));		debug("Connectionless MTU size is %d", audit->mtu);		break;	case 0x0001:		debug("Connectionless MTU is not supported");		break;	}}static void handle_features_response(struct audit *audit, const l2cap_info_rsp *rsp){	audit->mask_result = btohs(rsp->result);	switch (audit->mask_result) {	case 0x0000:		audit->mask = btohl(bt_get_unaligned((uint32_t *) rsp->data));		debug("Extended feature mask is 0x%04x", audit->mask);		if (audit->mask & 0x01)			debug("  Flow control mode");		if (audit->mask & 0x02)			debug("  Retransmission mode");		if (audit->mask & 0x04)			debug("  Bi-directional QoS");		break;	case 0x0001:		debug("Extended feature mask is not supported");		break;	}}static gboolean l2raw_data_callback(GIOChannel *io, GIOCondition cond, struct audit *audit){	unsigned char buf[48];	l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr *) buf;	l2cap_info_req *req = (l2cap_info_req *) (buf + L2CAP_CMD_HDR_SIZE);	l2cap_info_rsp *rsp = (l2cap_info_rsp *) (buf + L2CAP_CMD_HDR_SIZE);	int sk, ret, expected;	if (cond & G_IO_NVAL) {		g_io_channel_unref(io);		return FALSE;	}	if (cond & (G_IO_ERR | G_IO_HUP))		goto failed;	sk = g_io_channel_unix_get_fd(io);	memset(buf, 0, sizeof(buf));	if (audit->state == AUDIT_STATE_MTU)		expected = L2CAP_CMD_HDR_SIZE + L2CAP_INFO_RSP_SIZE + 2;	else		expected = L2CAP_CMD_HDR_SIZE + L2CAP_INFO_RSP_SIZE + 4;	ret = recv(sk, buf, expected, 0);	if (ret < 0) {		error("Can't receive info response: %s (%d)", strerror(errno), errno);		goto failed;	}	if (ret < L2CAP_CMD_HDR_SIZE) {		error("Too little data for l2cap response");		goto failed;	}	if (cmd->code != L2CAP_INFO_RSP)		return TRUE;	if (ret < L2CAP_CMD_HDR_SIZE + L2CAP_INFO_RSP_SIZE) {		error("Too little data for l2cap info response");		goto failed;	}	switch (audit->state) {	case AUDIT_STATE_MTU:		if (rsp->type != htobs(0x0001))			return TRUE;		if (audit->timeout) {			g_source_remove(audit->timeout);			audit->timeout = 0;		}		handle_mtu_response(audit, rsp);		memset(buf, 0, sizeof(buf));		cmd->code  = L2CAP_INFO_REQ;		cmd->ident = 43;		cmd->len   = htobs(2);		req->type  = htobs(0x0002);		if (send(sk, buf, L2CAP_CMD_HDR_SIZE + L2CAP_INFO_REQ_SIZE, 0) < 0) {			error("Can't send info request:", strerror(errno), errno);			goto failed;		}		audit->timeout = g_timeout_add(L2INFO_TIMEOUT, (GSourceFunc)						l2raw_input_timer, audit);		audit->state = AUDIT_STATE_FEATURES;		return TRUE;	case AUDIT_STATE_FEATURES:		if (rsp->type != htobs(0x0002))			return TRUE;		if (audit->timeout) {			g_source_remove(audit->timeout);			audit->timeout = 0;		}		handle_features_response(audit, rsp);		break;	}	write_l2cap_info(&audit->local, &audit->peer,				audit->mtu_result, audit->mtu,				audit->mask_result, audit->mask);failed:	if (audit->timeout) {		g_source_remove(audit->timeout);		audit->timeout = 0;	}	send_audit_status(audit, "AuditRemoteDeviceComplete");	g_io_channel_close(io);	g_io_channel_unref(io);	audits = g_slist_remove(audits, audit);	name_listener_remove(audit->conn, audit->requestor,				(name_cb_t) audit_requestor_exited, audit);	process_audits_list(audit->adapter_path);	audit_free(audit);	return FALSE;}static gboolean l2raw_connect_complete(GIOChannel *io, GIOCondition cond, struct audit *audit){	unsigned char buf[48];	l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr *) buf;	l2cap_info_req *req = (l2cap_info_req *) (buf + L2CAP_CMD_HDR_SIZE);	socklen_t len;	int sk, ret;	struct adapter *adapter = NULL;	if (cond & G_IO_NVAL) {		g_io_channel_unref(io);		return FALSE;	}	dbus_connection_get_object_user_data(audit->conn, audit->adapter_path,						(void *) &adapter);	if (adapter)		bacpy(&adapter->agents_disabled, BDADDR_ANY);	if (cond & (G_IO_ERR | G_IO_HUP)) {		error("Error on raw l2cap socket");		goto failed;

⌨️ 快捷键说明

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