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

📄 control.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2006-2007  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 <stdlib.h>#include <stdint.h>#include <errno.h>#include <unistd.h>#include <assert.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <netinet/in.h>#include <bluetooth/bluetooth.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <bluetooth/l2cap.h>#include <glib.h>#include <dbus/dbus.h>#include <gdbus.h>#include "dbus-service.h"#include "logging.h"#include "uinput.h"#include "device.h"#include "manager.h"#include "avdtp.h"#include "control.h"#include "sdpd.h"#include "glib-helper.h"#define AVCTP_PSM 23/* Message types */#define AVCTP_COMMAND		0#define AVCTP_RESPONSE		1/* Packet types */#define AVCTP_PACKET_SINGLE	0#define AVCTP_PACKET_START	1#define AVCTP_PACKET_CONTINUE	2#define AVCTP_PACKET_END	3/* ctype entries */#define CTYPE_CONTROL		0x0#define CTYPE_STATUS		0x1#define CTYPE_ACCEPTED		0x9#define CTYPE_STABLE		0xC/* opcodes */#define OP_UNITINFO		0x30#define OP_SUBUNITINFO		0x31#define OP_PASSTHROUGH		0x7c/* subunits of interest */#define SUBUNIT_PANEL		0x09/* operands in passthrough commands */#define VOLUP_OP		0x41#define VOLDOWN_OP		0x42#define MUTE_OP			0x43#define PLAY_OP			0x44#define STOP_OP			0x45#define PAUSE_OP		0x46#define REWIND_OP		0x48#define FAST_FORWARD_OP		0x49#define NEXT_OP			0x4b#define PREV_OP			0x4cstatic DBusConnection *connection = NULL;static uint32_t tg_record_id = 0;static uint32_t ct_record_id = 0;static GIOChannel *avctp_server = NULL;static GSList *sessions = NULL;typedef enum {	AVCTP_STATE_DISCONNECTED = 0,	AVCTP_STATE_CONNECTING,	AVCTP_STATE_CONNECTED} avctp_state_t;#if __BYTE_ORDER == __LITTLE_ENDIANstruct avctp_header {	uint8_t ipid:1;	uint8_t cr:1;	uint8_t packet_type:2;	uint8_t transaction:4;	uint16_t pid;} __attribute__ ((packed));struct avrcp_header {	uint8_t code:4;	uint8_t _hdr0:4;	uint8_t subunit_id:3;	uint8_t subunit_type:5;	uint8_t opcode;} __attribute__ ((packed));#elif __BYTE_ORDER == __BIG_ENDIANstruct avctp_header {	uint8_t transaction:4;	uint8_t packet_type:2;	uint8_t cr:1;	uint8_t ipid:1;	uint16_t pid;} __attribute__ ((packed));struct avrcp_header {	uint8_t _hdr0:4;	uint8_t code:4;	uint8_t subunit_type:5;	uint8_t subunit_id:3;	uint8_t opcode;} __attribute__ ((packed));#else#error "Unknown byte order"#endifstruct avctp {	struct audio_device *dev;	avctp_state_t state;	bdaddr_t src;	bdaddr_t dst;	int uinput;	int sock;	guint io;	uint16_t mtu;};struct control {	struct avctp *session;};static sdp_record_t *avrcp_ct_record(){	sdp_list_t *svclass_id, *pfseq, *apseq, *root;	uuid_t root_uuid, l2cap, avctp, avrct;	sdp_profile_desc_t profile[1];	sdp_list_t *aproto, *proto[2];	sdp_record_t *record;	sdp_data_t *psm, *version, *features;	uint16_t lp = AVCTP_PSM, ver = 0x0103, feat = 0x000f;	record = sdp_record_alloc();	if (!record)		return NULL;	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);	root = sdp_list_append(0, &root_uuid);	sdp_set_browse_groups(record, root);	/* Service Class ID List */	sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);	svclass_id = sdp_list_append(0, &avrct);	sdp_set_service_classes(record, svclass_id);	/* Protocol Descriptor List */	sdp_uuid16_create(&l2cap, L2CAP_UUID);	proto[0] = sdp_list_append(0, &l2cap);	psm = sdp_data_alloc(SDP_UINT16, &lp);	proto[0] = sdp_list_append(proto[0], psm);	apseq = sdp_list_append(0, proto[0]);	sdp_uuid16_create(&avctp, AVCTP_UUID);	proto[1] = sdp_list_append(0, &avctp);	version = sdp_data_alloc(SDP_UINT16, &ver);	proto[1] = sdp_list_append(proto[1], version);	apseq = sdp_list_append(apseq, proto[1]);	aproto = sdp_list_append(0, apseq);	sdp_set_access_protos(record, aproto);	/* Bluetooth Profile Descriptor List */	sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);	profile[0].version = ver;	pfseq = sdp_list_append(0, &profile[0]);	sdp_set_profile_descs(record, pfseq);	features = sdp_data_alloc(SDP_UINT16, &feat);	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);	sdp_set_info_attr(record, "AVRCP CT", 0, 0);	free(psm);	free(version);	sdp_list_free(proto[0], 0);	sdp_list_free(proto[1], 0);	sdp_list_free(apseq, 0);	sdp_list_free(pfseq, 0);	sdp_list_free(aproto, 0);	sdp_list_free(root, 0);	sdp_list_free(svclass_id, 0);	return record;}static sdp_record_t *avrcp_tg_record(){	sdp_list_t *svclass_id, *pfseq, *apseq, *root;	uuid_t root_uuid, l2cap, avctp, avrtg;	sdp_profile_desc_t profile[1];	sdp_list_t *aproto, *proto[2];	sdp_record_t *record;	sdp_data_t *psm, *version, *features;	uint16_t lp = AVCTP_PSM, ver = 0x0103, feat = 0x000f;	record = sdp_record_alloc();	if (!record)		return NULL;	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);	root = sdp_list_append(0, &root_uuid);	sdp_set_browse_groups(record, root);	/* Service Class ID List */	sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);	svclass_id = sdp_list_append(0, &avrtg);	sdp_set_service_classes(record, svclass_id);	/* Protocol Descriptor List */	sdp_uuid16_create(&l2cap, L2CAP_UUID);	proto[0] = sdp_list_append(0, &l2cap);	psm = sdp_data_alloc(SDP_UINT16, &lp);	proto[0] = sdp_list_append(proto[0], psm);	apseq = sdp_list_append(0, proto[0]);	sdp_uuid16_create(&avctp, AVCTP_UUID);	proto[1] = sdp_list_append(0, &avctp);	version = sdp_data_alloc(SDP_UINT16, &ver);	proto[1] = sdp_list_append(proto[1], version);	apseq = sdp_list_append(apseq, proto[1]);	aproto = sdp_list_append(0, apseq);	sdp_set_access_protos(record, aproto);	/* Bluetooth Profile Descriptor List */	sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);	profile[0].version = ver;	pfseq = sdp_list_append(0, &profile[0]);	sdp_set_profile_descs(record, pfseq);	features = sdp_data_alloc(SDP_UINT16, &feat);	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);	sdp_set_info_attr(record, "AVRCP TG", 0, 0);	free(psm);	free(version);	sdp_list_free(proto[0], 0);	sdp_list_free(proto[1], 0);	sdp_list_free(apseq, 0);	sdp_list_free(aproto, 0);	sdp_list_free(pfseq, 0);	sdp_list_free(root, 0);	sdp_list_free(svclass_id, 0);	return record;}static struct avctp *find_session(const bdaddr_t *src, const bdaddr_t *dst){	GSList *l;	for (l = sessions; l != NULL; l = g_slist_next(l)) {		struct avctp *s = l->data;		if (bacmp(src, &s->src) || bacmp(dst, &s->dst))			continue;		return s;	}	return NULL;}static struct avctp *avctp_get(const bdaddr_t *src, const bdaddr_t *dst){	struct avctp *session;	assert(src != NULL);	assert(dst != NULL);	session = find_session(src, dst);	if (session)		return session;	session = g_new0(struct avctp, 1);	session->uinput = -1;	session->sock = -1;	bacpy(&session->src, src);	bacpy(&session->dst, dst);	sessions = g_slist_append(sessions, session);	return session;}static int send_event(int fd, uint16_t type, uint16_t code, int32_t value){	struct uinput_event event;	memset(&event, 0, sizeof(event));	event.type	= type;	event.code	= code;	event.value	= value;	return write(fd, &event, sizeof(event));}static void send_key(int fd, uint16_t key, int pressed){	if (fd < 0)		return;	send_event(fd, EV_KEY, key, pressed);	send_event(fd, EV_SYN, SYN_REPORT, 0);}static void handle_panel_passthrough(struct avctp *session,					const unsigned char *operands,					int operand_count){	const char *status;	int pressed;	if (operand_count == 0)		return;	if (operands[0] & 0x80) {		status = "released";		pressed = 0;	} else {		status = "pressed";		pressed = 1;	}	switch (operands[0] & 0x7F) {	case PLAY_OP:		debug("AVRCP: PLAY %s", status);		send_key(session->uinput, KEY_PLAYPAUSE, pressed);		break;	case STOP_OP:		debug("AVRCP: STOP %s", status);		send_key(session->uinput, KEY_STOP, pressed);		break;	case PAUSE_OP:		debug("AVRCP: PAUSE %s", status);		send_key(session->uinput, KEY_PLAYPAUSE, pressed);		break;	case NEXT_OP:		debug("AVRCP: NEXT %s", status);		send_key(session->uinput, KEY_NEXTSONG, pressed);		break;	case PREV_OP:		debug("AVRCP: PREV %s", status);		send_key(session->uinput, KEY_PREVIOUSSONG, pressed);		break;	case REWIND_OP:		debug("AVRCP: REWIND %s", status);		send_key(session->uinput, KEY_REWIND, pressed);		break;	case FAST_FORWARD_OP:		debug("AVRCP: FAST FORWARD %s", status);		send_key(session->uinput, KEY_FORWARD, pressed);		break;	default:		debug("AVRCP: unknown button 0x%02X %s", operands[0] & 0x7F, status);		break;	}}static void avctp_unref(struct avctp *session){	sessions = g_slist_remove(sessions, session);	if (session->state == AVCTP_STATE_CONNECTED)		g_dbus_emit_signal(session->dev->conn,						session->dev->path,						AUDIO_CONTROL_INTERFACE,						"Disconnected",						DBUS_TYPE_INVALID);	if (session->sock >= 0)		close(session->sock);	if (session->io)		g_source_remove(session->io);	if (session->dev)		session->dev->control->session = NULL;	if (session->uinput >= 0) {		ioctl(session->uinput, UI_DEV_DESTROY);		close(session->uinput);	}	g_free(session);}static gboolean session_cb(GIOChannel *chan, GIOCondition cond,				gpointer data){	struct avctp *session = data;	unsigned char buf[1024], *operands;	struct avctp_header *avctp;	struct avrcp_header *avrcp;	int ret, packet_size, operand_count;	if (!(cond | G_IO_IN))		goto failed;	ret = read(session->sock, buf, sizeof(buf));	if (ret <= 0)		goto failed;	debug("Got %d bytes of data for AVCTP session %p", ret, session);	if (ret < sizeof(struct avctp_header)) {		error("Too small AVCTP packet");		goto failed;	}	packet_size = ret;	avctp = (struct avctp_header *) buf;	debug("AVCTP transaction %u, packet type %u, C/R %u, IPID %u, "			"PID 0x%04X",			avctp->transaction, avctp->packet_type,			avctp->cr, avctp->ipid, ntohs(avctp->pid));	ret -= sizeof(struct avctp_header);	if (ret < sizeof(struct avrcp_header)) {		error("Too small AVRCP packet");		goto failed;	}	avrcp = (struct avrcp_header *) (buf + sizeof(struct avctp_header));	ret -= sizeof(struct avrcp_header);	operands = buf + sizeof(struct avctp_header) + sizeof(struct avrcp_header);	operand_count = ret;	debug("AVRCP %s 0x%01X, subunit_type 0x%02X, subunit_id 0x%01X, "			"opcode 0x%02X, %d operands",

⌨️ 快捷键说明

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