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

📄 manager.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 <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <errno.h>#include <unistd.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/adapter.h"#include "../src/device.h"#include "../src/driver.h"#include "dbus-service.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"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_sdp_data {	struct audio_device *device;	DBusMessage *msg;	/* Method call or NULL */	GSList *records;	/* sdp_record_t * */	audio_sdp_state_t state;	create_dev_cb_t cb;	void *cb_data;};static DBusConnection *connection = NULL;static GSList *devices = NULL;static uint32_t hsp_ag_record_id = 0;static uint32_t hfp_ag_record_id = 0;static uint32_t hsp_hs_record_id = 0;static GIOChannel *hsp_ag_server = NULL;static GIOChannel *hfp_ag_server = NULL;static GIOChannel *hsp_hs_server = NULL;static struct enabled_interfaces enabled = {	.headset	= TRUE,	.gateway	= FALSE,	.sink		= TRUE,	.source		= FALSE,	.control	= TRUE,};static uint16_t get_service_uuid(const sdp_record_t *record){	sdp_list_t *classes;	uuid_t uuid;	uint16_t uuid16 = 0;	if (sdp_get_service_classes(record, &classes) < 0) {		error("Unable to get service classes from record");		return 0;	}	memcpy(&uuid, classes->data, sizeof(uuid));	if (!sdp_uuid128_to_uuid(&uuid)) {		error("Not a 16 bit UUID");		sdp_list_free(classes, free);		return 0;	}	if (uuid.type == SDP_UUID32) {		if (uuid.value.uuid32 > 0xFFFF) {			error("Not a 16 bit UUID");			goto done;		}		uuid16 = (uint16_t) uuid.value.uuid32;	} else		uuid16 = uuid.value.uuid16;done:	sdp_list_free(classes, free);	return uuid16;}gboolean server_is_enabled(uint16_t svc){	gboolean ret;	switch (svc) {	case HEADSET_SVCLASS_ID:		ret = (hsp_ag_server != NULL);		break;	case HEADSET_AGW_SVCLASS_ID:		ret = (hsp_hs_server != NULL);		break;	case HANDSFREE_SVCLASS_ID:		ret = (hfp_ag_server != NULL);		break;	case HANDSFREE_AGW_SVCLASS_ID:		ret = FALSE;		break;	case AUDIO_SINK_SVCLASS_ID:		return enabled.sink;	case AV_REMOTE_TARGET_SVCLASS_ID:	case AV_REMOTE_SVCLASS_ID:		return enabled.control;	default:		ret = FALSE;		break;	}	return ret;}static void handle_record(sdp_record_t *record, struct audio_device *device){	uint16_t uuid16;	uuid16 = get_service_uuid(record);	if (!server_is_enabled(uuid16))		return;	switch (uuid16) {	case HEADSET_SVCLASS_ID:		debug("Found Headset record");		if (device->headset)			headset_update(device, record, uuid16);		else			device->headset = headset_init(device,							record, uuid16);		break;	case HEADSET_AGW_SVCLASS_ID:		debug("Found Headset AG record");		break;	case HANDSFREE_SVCLASS_ID:		debug("Found Hansfree record");		if (device->headset)			headset_update(device, record, uuid16);		else			device->headset = headset_init(device,							record, uuid16);		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);		if (dbus_error_has_name(derr, DBUS_ERROR_NO_REPLY)) {			debug("Canceling authorization request");			service_cancel_auth(&device->src, &device->dst);		}		headset_set_state(device, HEADSET_STATE_DISCONNECTED);

⌨️ 快捷键说明

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