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

📄 control.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 <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 <glib.h>#include <dbus/dbus.h>#include <bluetooth/bluetooth.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <bluetooth/l2cap.h>#include "dbus.h"#include "dbus-helper.h"#include "logging.h"#include "uinput.h"#include "device.h"#include "manager.h"#include "avdtp.h"#include "control.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 device *dev;	avctp_state_t state;	bdaddr_t src;	bdaddr_t dst;	int uinput;	int sock;	guint io;	uint16_t mtu;	DBusPendingCall *pending_auth;};struct control {	struct avctp *session;};static int avrcp_ct_record(sdp_buf_t *buf){	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;	int ret = 0;	memset(&record, 0, sizeof(sdp_record_t));	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);	if (sdp_gen_record_pdu(&record, buf) < 0)		ret = -1;	else		ret = 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);	sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);	sdp_list_free(record.pattern, free);	return ret;}static int avrcp_tg_record(sdp_buf_t *buf){	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;	int ret = 0;	memset(&record, 0, sizeof(sdp_record_t));	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);	if (sdp_gen_record_pdu(&record, buf) < 0)		ret = -1;	else		ret = 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);	sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);	sdp_list_free(record.pattern, free);	return ret;}static GIOChannel *avctp_server_socket(void){	int sock, lm;	struct sockaddr_l2 addr;	GIOChannel *io;	sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);	if (sock < 0) {		error("AVCTP server socket: %s (%d)", strerror(errno), errno);		return NULL;	}	lm = L2CAP_LM_SECURE;	if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm)) < 0) {		error("AVCTP server setsockopt: %s (%d)", strerror(errno), errno);		close(sock);		return NULL;	}	memset(&addr, 0, sizeof(addr));	addr.l2_family = AF_BLUETOOTH;	bacpy(&addr.l2_bdaddr, BDADDR_ANY);	addr.l2_psm = htobs(AVCTP_PSM);	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		error("AVCTP server bind: %s", strerror(errno), errno);		close(sock);		return NULL;	}	if (listen(sock, 4) < 0) {		error("AVCTP server listen: %s", strerror(errno), errno);		close(sock);		return NULL;	}	io = g_io_channel_unix_new(sock);	if (!io) {		error("Unable to allocate new io channel");		close(sock);		return NULL;	}	return io;}static struct avctp *find_session(bdaddr_t *src, 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 void avctp_unref(struct avctp *session){	sessions = g_slist_remove(sessions, session);	if (session->pending_auth) {		manager_cancel_authorize(&session->dst, AVRCP_TARGET_UUID,						NULL);		dbus_pending_call_cancel(session->pending_auth);		dbus_pending_call_unref(session->pending_auth);	}	if (session->state == AVCTP_STATE_CONNECTED)		dbus_connection_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);	session->dev->control->session = NULL;	if (session->uinput >= 0) {		ioctl(session->uinput, UI_DEV_DESTROY);		close(session->uinput);	}	g_free(session);}static int uinput_create(char *name){	struct uinput_dev dev;	int fd, err;	fd = open("/dev/uinput", O_RDWR);	if (fd < 0) {		fd = open("/dev/input/uinput", O_RDWR);		if (fd < 0) {			fd = open("/dev/misc/uinput", O_RDWR);			if (fd < 0) {				err = errno;				error("Can't open input device: %s (%d)",							strerror(err), err);				return -err;			}		}	}	memset(&dev, 0, sizeof(dev));	if (name)		strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE);	dev.id.bustype = BUS_BLUETOOTH;	dev.id.vendor  = 0x0000;	dev.id.product = 0x0000;	dev.id.version = 0x0000;	if (write(fd, &dev, sizeof(dev)) < 0) {		err = errno;		error("Can't write device information: %s (%d)",						strerror(err), err);		close(fd);		errno = err;		return -err;	}	ioctl(fd, UI_SET_EVBIT, EV_KEY);	ioctl(fd, UI_SET_EVBIT, EV_REL);	ioctl(fd, UI_SET_EVBIT, EV_REP);	ioctl(fd, UI_SET_EVBIT, EV_SYN);	ioctl(fd, UI_SET_KEYBIT, KEY_PLAYPAUSE);	ioctl(fd, UI_SET_KEYBIT, KEY_STOP);	ioctl(fd, UI_SET_KEYBIT, KEY_NEXTSONG);	ioctl(fd, UI_SET_KEYBIT, KEY_PREVIOUSSONG);	ioctl(fd, UI_SET_KEYBIT, KEY_REWIND);	ioctl(fd, UI_SET_KEYBIT, KEY_FORWARD);	if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {		err = errno;		error("Can't create uinput device: %s (%d)",						strerror(err), err);		close(fd);		errno = err;		return -err;	}	return fd;}static struct avctp *avctp_get(bdaddr_t *src, bdaddr_t *dst){	struct avctp *session;	assert(src != NULL);	assert(dst != NULL);	session = find_session(src, dst);	if (session) {		if (session->pending_auth)			return NULL;		else			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 void init_uinput(struct avctp *session){	char address[18], *name;	ba2str(&session->dst, address);	name = session->dev->name ? session->dev->name : address;	session->uinput = uinput_create(name);	if (session->uinput < 0)		error("AVRCP: failed to init uinput for %s", name);	else		debug("AVRCP: uinput initialized for %s", name);}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;	}

⌨️ 快捷键说明

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