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

📄 manager.c

📁 BlueZ源码
💻 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 <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <stdint.h>#include <sys/stat.h>#include <dirent.h>#include <ctype.h>#include <signal.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/rfcomm.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <glib.h>#include <dbus/dbus.h>#include <gdbus.h>#include "glib-helper.h"#include "../src/manager.h"#include "../src/adapter.h"#include "../src/device.h"#include "logging.h"#include "textfile.h"#include "ipc.h"#include "device.h"#include "error.h"#include "avdtp.h"#include "a2dp.h"#include "headset.h"#include "gateway.h"#include "sink.h"#include "control.h"#include "manager.h"#include "sdpd.h"#include "telephony.h"typedef enum {	HEADSET	= 1 << 0,	GATEWAY	= 1 << 1,	SINK	= 1 << 2,	SOURCE	= 1 << 3,	CONTROL	= 1 << 4,	TARGET	= 1 << 5,	INVALID	= 1 << 6} audio_service_type;typedef enum {		GENERIC_AUDIO = 0,		ADVANCED_AUDIO,		AV_REMOTE,		GET_RECORDS} audio_sdp_state_t;struct audio_adapter {	bdaddr_t src;	char	*path;	uint32_t hsp_ag_record_id;	uint32_t hfp_ag_record_id;	uint32_t hsp_hs_record_id;	GIOChannel *hsp_ag_server;	GIOChannel *hfp_ag_server;	GIOChannel *hsp_hs_server;};static int max_connected_headsets = 1;static DBusConnection *connection = NULL;static GKeyFile *config = NULL;static GSList *adapters = NULL;static GSList *devices = NULL;static struct enabled_interfaces enabled = {	.hfp		= TRUE,	.headset	= TRUE,	.gateway	= FALSE,	.sink		= TRUE,	.source		= FALSE,	.control	= TRUE,};static struct audio_adapter *find_adapter(GSList *list, const char *path){	GSList *l;	for (l = list; l; l = l->next) {		struct audio_adapter *adapter = l->data;		if (g_str_equal(adapter->path, path))			return adapter;	}	return NULL;}gboolean server_is_enabled(bdaddr_t *src, uint16_t svc){	switch (svc) {	case HEADSET_SVCLASS_ID:		return enabled.headset;	case HEADSET_AGW_SVCLASS_ID:		return enabled.gateway;	case HANDSFREE_SVCLASS_ID:		return enabled.headset && enabled.hfp;	case HANDSFREE_AGW_SVCLASS_ID:		return  FALSE;	case AUDIO_SINK_SVCLASS_ID:		return enabled.sink;	case AV_REMOTE_TARGET_SVCLASS_ID:	case AV_REMOTE_SVCLASS_ID:		return enabled.control;	default:		return FALSE;	}}static void handle_uuid(const char *uuidstr, struct audio_device *device){	uuid_t uuid;	uint16_t uuid16;	if (bt_string2uuid(&uuid, uuidstr) < 0) {		error("%s not detected as an UUID-128", uuidstr);		return;	}	if (!sdp_uuid128_to_uuid(&uuid) && uuid.type != SDP_UUID16) {		error("Could not convert %s to a UUID-16", uuidstr);		return;	}	uuid16 = uuid.value.uuid16;	if (!server_is_enabled(&device->src, uuid16)) {		debug("audio handle_uuid: server not enabled for %s (0x%04x)",				uuidstr, uuid16);		return;	}	switch (uuid16) {	case HEADSET_SVCLASS_ID:		debug("Found Headset record");		if (device->headset)			headset_update(device, uuid16, uuidstr);		else			device->headset = headset_init(device, uuid16,							uuidstr);		break;	case HEADSET_AGW_SVCLASS_ID:		debug("Found Headset AG record");		break;	case HANDSFREE_SVCLASS_ID:		debug("Found Handsfree record");		if (device->headset)			headset_update(device, uuid16, uuidstr);		else			device->headset = headset_init(device, uuid16,							uuidstr);		break;	case HANDSFREE_AGW_SVCLASS_ID:		debug("Found Handsfree AG record");		break;	case AUDIO_SINK_SVCLASS_ID:		debug("Found Audio Sink");		if (device->sink == NULL)			device->sink = sink_init(device);		break;	case AUDIO_SOURCE_SVCLASS_ID:		debug("Found Audio Source");		break;	case AV_REMOTE_SVCLASS_ID:		debug("Found AV Remote");		if (device->control == NULL)			device->control = control_init(device);		if (device->sink && sink_is_active(device))			avrcp_connect(device);		break;	case AV_REMOTE_TARGET_SVCLASS_ID:		debug("Found AV Target");		if (device->control == NULL)			device->control = control_init(device);		if (device->sink && sink_is_active(device))			avrcp_connect(device);		break;	default:		debug("Unrecognized UUID: 0x%04X", uuid16);		break;	}}static sdp_record_t *hsp_ag_record(uint8_t ch){	sdp_list_t *svclass_id, *pfseq, *apseq, *root;	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;	uuid_t l2cap_uuid, rfcomm_uuid;	sdp_profile_desc_t profile;	sdp_record_t *record;	sdp_list_t *aproto, *proto[2];	sdp_data_t *channel;	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);	sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);	svclass_id = sdp_list_append(0, &svclass_uuid);	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);	sdp_set_service_classes(record, svclass_id);	sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);	profile.version = 0x0100;	pfseq = sdp_list_append(0, &profile);	sdp_set_profile_descs(record, pfseq);	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);	proto[0] = sdp_list_append(0, &l2cap_uuid);	apseq = sdp_list_append(0, proto[0]);	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);	proto[1] = sdp_list_append(0, &rfcomm_uuid);	channel = sdp_data_alloc(SDP_UINT8, &ch);	proto[1] = sdp_list_append(proto[1], channel);	apseq = sdp_list_append(apseq, proto[1]);	aproto = sdp_list_append(0, apseq);	sdp_set_access_protos(record, aproto);	sdp_set_info_attr(record, "Headset Audio Gateway", 0, 0);	sdp_data_free(channel);	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 *hsp_hs_record(uint8_t ch){	sdp_list_t *svclass_id, *pfseq, *apseq, *root;	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;	uuid_t l2cap_uuid, rfcomm_uuid;	sdp_profile_desc_t profile;	sdp_record_t *record;	sdp_list_t *aproto, *proto[2];	sdp_data_t *channel;	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);	sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID);	svclass_id = sdp_list_append(0, &svclass_uuid);	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);	sdp_set_service_classes(record, svclass_id);	sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);	profile.version = 0x0100;	pfseq = sdp_list_append(0, &profile);	sdp_set_profile_descs(record, pfseq);	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);	proto[0] = sdp_list_append(0, &l2cap_uuid);	apseq = sdp_list_append(0, proto[0]);	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);	proto[1] = sdp_list_append(0, &rfcomm_uuid);	channel = sdp_data_alloc(SDP_UINT8, &ch);	proto[1] = sdp_list_append(proto[1], channel);	apseq = sdp_list_append(apseq, proto[1]);	aproto = sdp_list_append(0, apseq);	sdp_set_access_protos(record, aproto);	sdp_set_info_attr(record, "Headset", 0, 0);	sdp_data_free(channel);	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 *hfp_ag_record(uint8_t ch, uint32_t feat){	sdp_list_t *svclass_id, *pfseq, *apseq, *root;	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;	uuid_t l2cap_uuid, rfcomm_uuid;	sdp_profile_desc_t profile;	sdp_list_t *aproto, *proto[2];	sdp_record_t *record;	sdp_data_t *channel, *features;	uint8_t netid = 0x01;	uint16_t sdpfeat;	sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);	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);	sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);	svclass_id = sdp_list_append(0, &svclass_uuid);	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);	sdp_set_service_classes(record, svclass_id);	sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);	profile.version = 0x0105;	pfseq = sdp_list_append(0, &profile);	sdp_set_profile_descs(record, pfseq);	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);	proto[0] = sdp_list_append(0, &l2cap_uuid);	apseq = sdp_list_append(0, proto[0]);	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);	proto[1] = sdp_list_append(0, &rfcomm_uuid);	channel = sdp_data_alloc(SDP_UINT8, &ch);	proto[1] = sdp_list_append(proto[1], channel);	apseq = sdp_list_append(apseq, proto[1]);	sdpfeat = (uint16_t) feat & 0xF;	features = sdp_data_alloc(SDP_UINT16, &sdpfeat);	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);	aproto = sdp_list_append(0, apseq);	sdp_set_access_protos(record, aproto);	sdp_set_info_attr(record, "Hands-Free Audio Gateway", 0, 0);	sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);	sdp_data_free(channel);	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 void auth_cb(DBusError *derr, void *user_data){	struct audio_device *device = user_data;	const char *uuid;	if (get_hfp_active(device))		uuid = HFP_AG_UUID;	else		uuid = HSP_AG_UUID;	if (derr && dbus_error_is_set(derr)) {		error("Access denied: %s", derr->message);		headset_set_state(device, HEADSET_STATE_DISCONNECTED);	} else {		char hs_address[18];		ba2str(&device->dst, hs_address);		debug("Accepted headset connection from %s for %s",						hs_address, device->path);		headset_set_authorized(device);	}}static void ag_io_cb(GIOChannel *chan, int err, const bdaddr_t *src,			const bdaddr_t *dst, gpointer data){	struct audio_adapter *adapter = data;	const char *server_uuid, *remote_uuid;	uint16_t svclass;	struct audio_device *device;	gboolean hfp_active;	if (err < 0) {		error("accept: %s (%d)", strerror(-err), -err);		return;	}	if (chan == adapter->hsp_ag_server) {		hfp_active = FALSE;		server_uuid = HSP_AG_UUID;		remote_uuid = HSP_HS_UUID;		svclass = HEADSET_SVCLASS_ID;	} else {		hfp_active = TRUE;		server_uuid = HFP_AG_UUID;		remote_uuid = HFP_HS_UUID;		svclass = HANDSFREE_SVCLASS_ID;	}	device = manager_get_device(src, dst);	if (!device)		goto drop;	if (!manager_allow_headset_connection(&device->src)) {		debug("Refusing headset: too many existing connections");		goto drop;	}	if (!device->headset)		btd_device_add_uuid(device->btd_dev, remote_uuid);	if (headset_get_state(device) > HEADSET_STATE_DISCONNECTED) {		debug("Refusing new connection since one already exists");		goto drop;	}	set_hfp_active(device, hfp_active);	if (headset_connect_rfcomm(device, chan) < 0) {		error("Allocating new GIOChannel failed!");		goto drop;	}	headset_set_state(device, HEADSET_STATE_CONNECT_IN_PROGRESS);	err = btd_request_authorization(&device->src, &device->dst,					server_uuid, auth_cb, device);	if (err < 0) {		debug("Authorization denied: %s", strerror(-err));		headset_set_state(device, HEADSET_STATE_DISCONNECTED);		return;	}	return;drop:	g_io_channel_close(chan);	g_io_channel_unref(chan);}static void hs_io_cb(GIOChannel *chan, int err, const bdaddr_t *src,		const bdaddr_t *dst, void *data){	/*Stub*/	return;}static int headset_server_init(struct audio_adapter *adapter){	uint8_t chan = DEFAULT_HS_AG_CHANNEL;	sdp_record_t *record;	gboolean master = TRUE;	GError *err = NULL;	uint32_t features, flags;	if (config) {		gboolean tmp;		tmp = g_key_file_get_boolean(config, "General", "Master",						&err);		if (err) {			debug("audio.conf: %s", err->message);			g_clear_error(&err);		} else			master = tmp;	}	flags = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;	if (master)		flags |= RFCOMM_LM_MASTER;	adapter->hsp_ag_server = bt_rfcomm_listen(&adapter->src, chan, flags,							ag_io_cb, adapter);	if (!adapter->hsp_ag_server)		goto failed;	record = hsp_ag_record(chan);	if (!record) {		error("Unable to allocate new service record");		goto failed;	}	if (add_record_to_server(&adapter->src, record) < 0) {		error("Unable to register HS AG service record");		sdp_record_free(record);		goto failed;	}	adapter->hsp_ag_record_id = record->handle;	features = headset_config_init(config);	if (!enabled.hfp)		return 0;	chan = DEFAULT_HF_AG_CHANNEL;	adapter->hfp_ag_server = bt_rfcomm_listen(&adapter->src, chan, flags,							ag_io_cb, adapter);

⌨️ 快捷键说明

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