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

📄 avdtp.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * *  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 <stdint.h>#include <errno.h>#include <unistd.h>#include <assert.h>#include <signal.h>#include <netinet/in.h>#include <glib.h>#include <bluetooth/bluetooth.h>#include <bluetooth/sdp.h>#include "dbus.h"#include "logging.h"#include "device.h"#include "manager.h"#include "control.h"#include "avdtp.h"#include <bluetooth/l2cap.h>#define AVDTP_PSM 25#define MAX_SEID 0x3E#define AVDTP_DISCOVER				0x01#define AVDTP_GET_CAPABILITIES			0x02#define AVDTP_SET_CONFIGURATION			0x03#define AVDTP_GET_CONFIGURATION			0x04#define AVDTP_RECONFIGURE			0x05#define AVDTP_OPEN				0x06#define AVDTP_START				0x07#define AVDTP_CLOSE				0x08#define AVDTP_SUSPEND				0x09#define AVDTP_ABORT				0x0A#define AVDTP_SECURITY_CONTROL			0x0B#define AVDTP_PKT_TYPE_SINGLE			0x00#define AVDTP_PKT_TYPE_START			0x01#define AVDTP_PKT_TYPE_CONTINUE			0x02#define AVDTP_PKT_TYPE_END			0x03#define AVDTP_MSG_TYPE_COMMAND			0x00#define AVDTP_MSG_TYPE_ACCEPT			0x02#define AVDTP_MSG_TYPE_REJECT			0x03#define REQ_TIMEOUT 4000#define DISCONNECT_TIMEOUT 5000#define STREAM_TIMEOUT 20000typedef enum {	AVDTP_SESSION_STATE_DISCONNECTED,	AVDTP_SESSION_STATE_CONNECTING,	AVDTP_SESSION_STATE_CONNECTED} avdtp_session_state_t;#if __BYTE_ORDER == __LITTLE_ENDIANstruct avdtp_header {	uint8_t message_type:2;	uint8_t packet_type:2;	uint8_t transaction:4;	uint8_t signal_id:6;	uint8_t rfa0:2;} __attribute__ ((packed));struct seid_info {	uint8_t rfa0:1;	uint8_t inuse:1;	uint8_t seid:6;	uint8_t rfa2:3;	uint8_t type:1;	uint8_t media_type:4;} __attribute__ ((packed));struct seid {	uint8_t rfa0:2;	uint8_t seid:6;} __attribute__ ((packed));#elif __BYTE_ORDER == __BIG_ENDIANstruct avdtp_header {	uint8_t transaction:4;	uint8_t packet_type:2;	uint8_t message_type:2;	uint8_t rfa0:2;	uint8_t signal_id:6;} __attribute__ ((packed));struct seid_info {	uint8_t seid:6;	uint8_t inuse:1;	uint8_t rfa0:1;	uint8_t media_type:4;	uint8_t type:1;	uint8_t rfa2:3;} __attribute__ ((packed));struct seid {	uint8_t seid:6;	uint8_t rfa0:2;} __attribute__ ((packed));#else#error "Unknown byte order"#endif/* packets */struct gen_req {	struct avdtp_header header;} __attribute__ ((packed));struct gen_resp {	struct avdtp_header header;} __attribute__ ((packed));struct discover_resp {	struct avdtp_header header;	struct seid_info seps[0];} __attribute__ ((packed));struct getcap_resp {	struct avdtp_header header;	uint8_t caps[0];} __attribute__ ((packed));struct start_req {	struct avdtp_header header;	struct seid first_seid;	struct seid other_seids[0];} __attribute__ ((packed));struct suspend_req {	struct avdtp_header header;	struct seid first_seid;	struct seid other_seids[0];} __attribute__ ((packed));struct seid_rej {	struct avdtp_header header;	uint8_t error;} __attribute__ ((packed));struct conf_rej {	struct avdtp_header header;	uint8_t category;	uint8_t error;} __attribute__ ((packed));#if __BYTE_ORDER == __LITTLE_ENDIANstruct seid_req {	struct avdtp_header header;	uint8_t rfa0:2;	uint8_t acp_seid:6;} __attribute__ ((packed));struct setconf_req {	struct avdtp_header header;	uint8_t rfa0:2;	uint8_t acp_seid:6;	uint8_t rfa1:2;	uint8_t int_seid:6;	uint8_t caps[0];} __attribute__ ((packed));struct stream_rej {	struct avdtp_header header;	uint8_t rfa0:2;	uint8_t acp_seid:6;	uint8_t error;} __attribute__ ((packed));struct reconf_req {	struct avdtp_header header;	uint8_t rfa0:2;	uint8_t acp_seid:6;	uint8_t serv_cap;	uint8_t serv_cap_len;	uint8_t caps[0];} __attribute__ ((packed));struct avdtp_general_rej {	uint8_t message_type:2;	uint8_t packet_type:2;	uint8_t transaction:4;	uint8_t rfa0;} __attribute__ ((packed));#elif __BYTE_ORDER == __BIG_ENDIANstruct seid_req {	struct avdtp_header header;	uint8_t acp_seid:6;	uint8_t rfa0:2;} __attribute__ ((packed));struct setconf_req {	struct avdtp_header header;	uint8_t acp_seid:6;	uint8_t rfa0:2;	uint8_t int_seid:6;	uint8_t rfa1:2;	uint8_t caps[0];} __attribute__ ((packed));struct stream_rej {	struct avdtp_header header;	uint8_t acp_seid:6;	uint8_t rfa0:2;	uint8_t error;} __attribute__ ((packed));struct reconf_req {	struct avdtp_header header;	uint8_t acp_seid:6;	uint8_t rfa0:2;	uint8_t serv_cap;	uint8_t serv_cap_len;	uint8_t caps[0];} __attribute__ ((packed));struct avdtp_general_rej {	uint8_t transaction:4;	uint8_t packet_type:2;	uint8_t message_type:2;	uint8_t rfa0;} __attribute__ ((packed));#else#error "Unknown byte order"#endifstruct pending_req {	struct avdtp_header *msg;	int msg_size;	struct avdtp_stream *stream; /* Set if the request targeted a stream */	guint timeout;};struct avdtp_remote_sep {	uint8_t seid;	uint8_t type;	uint8_t media_type;	struct avdtp_service_capability *codec;	GSList *caps; /* of type struct avdtp_service_capability */	struct avdtp_stream *stream;};struct avdtp_local_sep {	avdtp_state_t state;	struct avdtp_stream *stream;	struct seid_info info;	uint8_t codec;	GSList *caps;	struct avdtp_sep_ind *ind;	struct avdtp_sep_cfm *cfm;	void *user_data;};struct stream_callback {	avdtp_stream_state_cb cb;	void *user_data;	unsigned int id;};struct avdtp_stream {	int sock;	uint16_t imtu;	uint16_t omtu;	struct avdtp *session;	struct avdtp_local_sep *lsep;	uint8_t rseid;	GSList *caps;	GSList *callbacks;	struct avdtp_service_capability *codec;	guint io;		/* Transport GSource ID */	guint timer;		/* Waiting for other side to close or open				   the transport channel */	gboolean open_acp;	/* If we are in ACT role for Open */	gboolean close_int;	/* If we are in INT role for Close */	guint idle_timer;};/* Structure describing an AVDTP connection between two devices */struct avdtp {	int ref;	int free_lock;	bdaddr_t src;	bdaddr_t dst;	avdtp_session_state_t last_state;	avdtp_session_state_t state;	guint io;	int sock;	GSList *seps; /* Elements of type struct avdtp_remote_sep * */	GSList *streams; /* Elements of type struct avdtp_stream * */	GSList *req_queue; /* Elements of type struct pending_req * */	GSList *prio_queue; /* Same as req_queue but is processed before it */	struct avdtp_stream *pending_open;	uint16_t mtu;	char *buf;	avdtp_discover_cb_t discov_cb;	void *user_data;	struct pending_req *req;	guint dc_timer;	DBusPendingCall *pending_auth;};static uint8_t free_seid = 1;static GSList *local_seps = NULL;static GIOChannel *avdtp_server = NULL;static GSList *sessions = NULL;static int send_request(struct avdtp *session, gboolean priority,			struct avdtp_stream *stream, void *buffer, int size);static gboolean avdtp_parse_resp(struct avdtp *session,					struct avdtp_stream *stream,					struct avdtp_header *header, int size);static gboolean avdtp_parse_rej(struct avdtp *session,				struct avdtp_stream *stream,				struct avdtp_header *header, int size);static int process_queue(struct avdtp *session);static void connection_lost(struct avdtp *session, int err);static void avdtp_sep_set_state(struct avdtp *session,				struct avdtp_local_sep *sep,				avdtp_state_t state);static const char *avdtp_statestr(avdtp_state_t state){	switch (state) {	case AVDTP_STATE_IDLE:		return "IDLE";	case AVDTP_STATE_CONFIGURED:		return "CONFIGURED";	case AVDTP_STATE_OPEN:		return "OPEN";	case AVDTP_STATE_STREAMING:		return "STREAMING";	case AVDTP_STATE_CLOSING:		return "CLOSING";	case AVDTP_STATE_ABORTING:		return "ABORTING";	default:		return "<unknown state>";	}}static gboolean avdtp_send(struct avdtp *session, void *data, int len){	int ret;	if (session->sock < 0) {		error("avdtp_send: session is closed");		return FALSE;	}	ret = send(session->sock, data, len, 0);	if (ret < 0)		ret = -errno;	else if (ret != len)		ret = -EIO;	if (ret < 0) {		error("avdtp_send: %s (%d)", strerror(-ret), -ret);		return FALSE;	}	return TRUE;}static void pending_req_free(struct pending_req *req){	if (req->timeout)		g_source_remove(req->timeout);	g_free(req->msg);	g_free(req);}static gboolean stream_close_timeout(gpointer user_data){	struct avdtp_stream *stream = user_data;	debug("Timed out waiting for peer to close the transport channel");	stream->timer = 0;	close(stream->sock);	return FALSE;}static gboolean stream_open_timeout(gpointer user_data){	struct avdtp_stream *stream = user_data;	debug("Timed out waiting for peer to open the transport channel");	stream->timer = 0;	stream->session->pending_open = NULL;	avdtp_abort(stream->session, stream);	return FALSE;}static gboolean disconnect_timeout(gpointer user_data){	struct avdtp *session = user_data;	assert(session->ref == 1);	session->dc_timer = 0;	connection_lost(session, -ETIMEDOUT);	return FALSE;}static void remove_disconnect_timer(struct avdtp *session){	g_source_remove(session->dc_timer);	session->dc_timer = 0;}static void set_disconnect_timer(struct avdtp *session){	if (session->dc_timer)		remove_disconnect_timer(session);	session->dc_timer = g_timeout_add(DISCONNECT_TIMEOUT,						disconnect_timeout, session);}void avdtp_error_init(struct avdtp_error *err, uint8_t type, int id){	err->type = type;	switch (type) {	case AVDTP_ERROR_ERRNO:		err->err.posix_errno = id;		break;	case AVDTP_ERROR_ERROR_CODE:		err->err.error_code = id;		break;	}}avdtp_error_type_t avdtp_error_type(struct avdtp_error *err){	return err->type;}int avdtp_error_error_code(struct avdtp_error *err){	assert(err->type == AVDTP_ERROR_ERROR_CODE);	return err->err.error_code;}int avdtp_error_posix_errno(struct avdtp_error *err){	assert(err->type == AVDTP_ERROR_ERRNO);	return err->err.posix_errno;}static struct avdtp_stream *find_stream_by_rseid(struct avdtp *session,							uint8_t rseid){	GSList *l;	for (l = session->streams; l != NULL; l = g_slist_next(l)) {		struct avdtp_stream *stream = l->data;		if (stream->rseid == rseid)			return stream;	}	return NULL;}static struct avdtp_remote_sep *find_remote_sep(GSList *seps, uint8_t seid){	GSList *l;	for (l = seps; l != NULL; l = g_slist_next(l)) {		struct avdtp_remote_sep *sep = l->data;		if (sep->seid == seid)			return sep;	}	return NULL;}static void stream_free(struct avdtp_stream *stream){	struct avdtp_remote_sep *rsep;	stream->lsep->info.inuse = 0;	stream->lsep->stream = NULL;	rsep = find_remote_sep(stream->session->seps, stream->rseid);	if (rsep)		rsep->stream = NULL;	if (stream->timer)		g_source_remove(stream->timer);	if (stream->sock >= 0)		close(stream->sock);	if (stream->io)		g_source_remove(stream->io);	g_slist_foreach(stream->callbacks, (GFunc) g_free, NULL);	g_slist_free(stream->callbacks);	g_slist_foreach(stream->caps, (GFunc) g_free, NULL);	g_slist_free(stream->caps);

⌨️ 快捷键说明

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