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

📄 avdtp.c

📁 BlueZ源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (omtu)		*omtu = stream->omtu;	if (imtu)		*imtu = stream->imtu;	if (caps)		*caps = stream->caps;	return TRUE;}static int process_queue(struct avdtp *session){	GSList **queue, *l;	struct pending_req *req;	if (session->req)		return 0;	if (session->prio_queue)		queue = &session->prio_queue;	else		queue = &session->req_queue;	if (!*queue)		return 0;	l = *queue;	req = l->data;	*queue = g_slist_remove(*queue, req);	return send_req(session, FALSE, req);}struct avdtp_service_capability *avdtp_get_codec(struct avdtp_remote_sep *sep){	return sep->codec;}struct avdtp_service_capability *avdtp_service_cap_new(uint8_t category,							void *data, int length){	struct avdtp_service_capability *cap;	if (category < AVDTP_MEDIA_TRANSPORT || category > AVDTP_MEDIA_CODEC)		return NULL;	cap = g_malloc(sizeof(struct avdtp_service_capability) + length);	cap->category = category;	cap->length = length;	memcpy(cap->data, data, length);	return cap;}int avdtp_discover(struct avdtp *session, avdtp_discover_cb_t cb,			void *user_data){	struct gen_req req;	int ret;	if (session->discov_cb)		return -EBUSY;	if (session->seps) {		cb(session, session->seps, NULL, user_data);		return 0;	}	memset(&req, 0, sizeof(req));	init_request(&req.header, AVDTP_DISCOVER);	ret = send_request(session, FALSE, NULL, &req, sizeof(req));	if (ret == 0) {		session->discov_cb = cb;		session->user_data = user_data;	}	return ret;}int avdtp_get_seps(struct avdtp *session, uint8_t acp_type, uint8_t media_type,			uint8_t codec, struct avdtp_local_sep **lsep,			struct avdtp_remote_sep **rsep){	GSList *l;	uint8_t int_type;	int_type = acp_type == AVDTP_SEP_TYPE_SINK ?				AVDTP_SEP_TYPE_SOURCE : AVDTP_SEP_TYPE_SINK;	*lsep = find_local_sep(session->server, int_type, media_type, codec);	if (!*lsep)		return -EINVAL;	for (l = session->seps; l != NULL; l = g_slist_next(l)) {		struct avdtp_remote_sep *sep = l->data;		struct avdtp_service_capability *cap;		struct avdtp_media_codec_capability *codec_data;		if (sep->type != acp_type)			continue;		if (sep->media_type != media_type)			continue;		if (!sep->codec)			continue;		cap = sep->codec;		codec_data = (void *) cap->data;		if (codec_data->media_codec_type != codec)			continue;		if (!sep->stream) {			*rsep = sep;			return 0;		}	}	return -EINVAL;}gboolean avdtp_stream_remove_cb(struct avdtp *session,				struct avdtp_stream *stream,				unsigned int id){	GSList *l;	struct stream_callback *cb;	if (!stream)		return FALSE;	for (cb = NULL, l = stream->callbacks; l != NULL; l = l->next) {		struct stream_callback *tmp = l->data;		if (tmp && tmp->id == id) {			cb = tmp;			break;		}	}	if (!cb)		return FALSE;	stream->callbacks = g_slist_remove(stream->callbacks, cb);	g_free(cb);	return TRUE;}unsigned int avdtp_stream_add_cb(struct avdtp *session,					struct avdtp_stream *stream,					avdtp_stream_state_cb cb, void *data){	struct stream_callback *stream_cb;	static unsigned int id = 0;	stream_cb = g_new(struct stream_callback, 1);	stream_cb->cb = cb;	stream_cb->user_data = data;	stream_cb->id = ++id;	stream->callbacks = g_slist_append(stream->callbacks, stream_cb);;	return stream_cb->id;}int avdtp_get_configuration(struct avdtp *session, struct avdtp_stream *stream){	struct seid_req req;	if (session->state < AVDTP_SESSION_STATE_CONNECTED)		return -EINVAL;	memset(&req, 0, sizeof(req));	init_request(&req.header, AVDTP_GET_CONFIGURATION);	req.acp_seid = stream->rseid;	return send_request(session, FALSE, stream, &req, sizeof(req));}static void copy_capabilities(gpointer data, gpointer user_data){	struct avdtp_service_capability *src_cap = data;	struct avdtp_service_capability *dst_cap;	GSList **l = user_data;	dst_cap = avdtp_service_cap_new(src_cap->category, src_cap->data,					src_cap->length);	*l = g_slist_append(*l, dst_cap);}int avdtp_set_configuration(struct avdtp *session,				struct avdtp_remote_sep *rsep,				struct avdtp_local_sep *lsep,				GSList *caps,				struct avdtp_stream **stream){	struct setconf_req *req;	struct avdtp_stream *new_stream;	unsigned char *ptr;	int ret, caps_len;	struct avdtp_service_capability *cap;	GSList *l;	if (session->state != AVDTP_SESSION_STATE_CONNECTED)		return -ENOTCONN;	if (!(lsep && rsep))		return -EINVAL;	debug("avdtp_set_configuration(%p): int_seid=%u, acp_seid=%u",			session, lsep->info.seid, rsep->seid);	new_stream = g_new0(struct avdtp_stream, 1);	new_stream->sock = -1;	new_stream->session = session;	new_stream->lsep = lsep;	new_stream->rseid = rsep->seid;	g_slist_foreach(caps, copy_capabilities, &new_stream->caps);	/* Calculate total size of request */	for (l = caps, caps_len = 0; l != NULL; l = g_slist_next(l)) {		cap = l->data;		caps_len += cap->length + 2;	}	req = g_malloc0(sizeof(struct setconf_req) + caps_len);	init_request(&req->header, AVDTP_SET_CONFIGURATION);	req->int_seid = lsep->info.seid;	req->acp_seid = rsep->seid;	/* Copy the capabilities into the request */	for (l = caps, ptr = req->caps; l != NULL; l = g_slist_next(l)) {		cap = l->data;		memcpy(ptr, cap, cap->length + 2);		ptr += cap->length + 2;	}	ret = send_request(session, FALSE, new_stream, req,				sizeof(struct setconf_req) + caps_len);	if (ret < 0)		stream_free(new_stream);	else {		lsep->info.inuse = 1;		lsep->stream = new_stream;		rsep->stream = new_stream;		session->streams = g_slist_append(session->streams, new_stream);		if (stream)			*stream = new_stream;	}	g_free(req);	return ret;}int avdtp_reconfigure(struct avdtp *session, GSList *caps,			struct avdtp_stream *stream){	struct reconf_req *req;	unsigned char *ptr;	int caps_len;	GSList *l;	struct avdtp_service_capability *cap;	if (!g_slist_find(session->streams, stream))		return -EINVAL;	if (stream->lsep->state != AVDTP_STATE_OPEN)		return -EINVAL;	/* Calculate total size of request */	for (l = caps, caps_len = 0; l != NULL; l = g_slist_next(l)) {		cap = l->data;		caps_len += cap->length + 2;	}	req = g_malloc0(sizeof(struct reconf_req) + caps_len);	init_request(&req->header, AVDTP_RECONFIGURE);	req->acp_seid = stream->rseid;	/* Copy the capabilities into the request */	for (l = caps, ptr = req->caps; l != NULL; l = g_slist_next(l)) {		cap = l->data;		memcpy(ptr, cap, cap->length + 2);		ptr += cap->length + 2;	}	return send_request(session, FALSE, stream, req, sizeof(*req)				+ caps_len);}int avdtp_open(struct avdtp *session, struct avdtp_stream *stream){	struct seid_req req;	if (!g_slist_find(session->streams, stream))		return -EINVAL;	if (stream->lsep->state > AVDTP_STATE_CONFIGURED)		return -EINVAL;	memset(&req, 0, sizeof(req));	init_request(&req.header, AVDTP_OPEN);	req.acp_seid = stream->rseid;	return send_request(session, FALSE, stream, &req, sizeof(req));}int avdtp_start(struct avdtp *session, struct avdtp_stream *stream){	struct start_req req;	if (!g_slist_find(session->streams, stream))		return -EINVAL;	if (stream->lsep->state != AVDTP_STATE_OPEN)		return -EINVAL;	memset(&req, 0, sizeof(req));	init_request(&req.header, AVDTP_START);	req.first_seid.seid = stream->rseid;	return send_request(session, FALSE, stream, &req, sizeof(req));}int avdtp_close(struct avdtp *session, struct avdtp_stream *stream){	struct seid_req req;	int ret;	if (!g_slist_find(session->streams, stream))		return -EINVAL;	if (stream->lsep->state < AVDTP_STATE_OPEN)		return -EINVAL;	memset(&req, 0, sizeof(req));	init_request(&req.header, AVDTP_CLOSE);	req.acp_seid = stream->rseid;	ret = send_request(session, FALSE, stream, &req, sizeof(req));	if (ret == 0)		stream->close_int = TRUE;	return ret;}int avdtp_suspend(struct avdtp *session, struct avdtp_stream *stream){	struct seid_req req;	if (!g_slist_find(session->streams, stream))		return -EINVAL;	if (stream->lsep->state <= AVDTP_STATE_OPEN)		return -EINVAL;	memset(&req, 0, sizeof(req));	init_request(&req.header, AVDTP_SUSPEND);	req.acp_seid = stream->rseid;	return send_request(session, FALSE, stream, &req, sizeof(req));}int avdtp_abort(struct avdtp *session, struct avdtp_stream *stream){	struct seid_req req;	int ret;	if (!g_slist_find(session->streams, stream))		return -EINVAL;	if (stream->lsep->state <= AVDTP_STATE_OPEN)		return -EINVAL;	memset(&req, 0, sizeof(req));	init_request(&req.header, AVDTP_ABORT);	req.acp_seid = stream->rseid;	ret = send_request(session, FALSE, stream, &req, sizeof(req));	if (ret == 0)		avdtp_sep_set_state(session, stream->lsep,					AVDTP_STATE_ABORTING);	return ret;}struct avdtp_local_sep *avdtp_register_sep(const bdaddr_t *src, uint8_t type,						uint8_t media_type,						uint8_t codec_type,						struct avdtp_sep_ind *ind,						struct avdtp_sep_cfm *cfm,						void *user_data){	struct avdtp_server *server;	struct avdtp_local_sep *sep;	server = find_server(servers, src);	if (!server)		return NULL;	if (g_slist_length(server->seps) > MAX_SEID)		return NULL;	sep = g_new0(struct avdtp_local_sep, 1);	sep->state = AVDTP_STATE_IDLE;	sep->info.seid = g_slist_length(server->seps) + 1;	sep->info.type = type;	sep->info.media_type = media_type;	sep->codec = codec_type;	sep->ind = ind;	sep->cfm = cfm;	sep->user_data = user_data;	sep->server = server;	debug("SEP %p registered: type:%d codec:%d seid:%d", sep,			sep->info.type, sep->codec, sep->info.seid);	server->seps = g_slist_append(server->seps, sep);	return sep;}int avdtp_unregister_sep(struct avdtp_local_sep *sep){	struct avdtp_server *server;	if (!sep)		return -EINVAL;	if (sep->info.inuse)		return -EBUSY;	server = sep->server;	server->seps = g_slist_remove(server->seps, sep);	g_free(sep);	return 0;}static void auth_cb(DBusError *derr, void *user_data){	struct avdtp *session = user_data;	struct audio_device *dev;	GIOChannel *io;	if (derr && dbus_error_is_set(derr)) {		error("Access denied: %s", derr->message);		connection_lost(session, -EACCES);		return;	}	session->buf = g_malloc0(session->mtu);	set_disconnect_timer(session);	session->state = AVDTP_SESSION_STATE_CONNECTED;	dev = manager_find_device(&session->dst, AUDIO_CONTROL_INTERFACE,					FALSE);	if (dev)		avrcp_connect(dev);	g_source_remove(session->io);	io = g_io_channel_unix_new(session->sock);	session->io = g_io_add_watch(io,				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,				(GIOFunc) session_cb, session);	g_io_channel_unref(io);}static void avdtp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src,		const bdaddr_t *dst, gpointer data){	int sk;	socklen_t size;	struct l2cap_options l2o;	struct avdtp *session;	struct audio_device *dev;	char address[18];	if (err < 0) {		error("accept: %s (%d)", strerror(-err), -err);		return;	}	sk = g_io_channel_unix_get_fd(chan);	ba2str(dst, address);	debug("AVDTP: incoming connect from %s", address);	memset(&l2o, 0, sizeof(l2o));	size = sizeof(l2o);	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &size) < 0) {		error("getsockopt(L2CAP_OPTIONS): %s (%d)", strerror(errno),			errno);		goto drop;	}	session = avdtp_get_internal(src, dst);	if (session->pending_open && session->pending_open->open_acp) {		handle_transport_connect(session, sk, l2o.imtu, l2o.omtu);		return;	}	if (session->sock >= 0) {		error("Refusing unexpected connect from %s", address);		goto drop;	}	dev = manager_get_device(src, dst);	if (!dev) {		error("Unable to get audio device object for %s", address);		goto drop;	}	session->mtu = l2o.imtu;	session->sock = sk;	session->io = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,					(GIOFunc) session_cb, session);	err = btd_request_authorization(src, dst, ADVANCED_AUDIO_UUID,				auth_cb, session);	if (err < 0) {		avdtp_unref(session);		goto drop;	}	g_io_channel_unref(chan);	return;drop:	g_io_channel_close(chan);	g_io_channel_unref(chan);}static GIOChannel *avdtp_server_socket(const bdaddr_t *src, gboolean master){	int lm = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;	if (master)		lm |= L2CAP_LM_MASTER;	return bt_l2cap_listen(src, AVDTP_PSM, 0, lm, avdtp_server_cb,			NULL);}const char *avdtp_strerror(struct avdtp_error *err){	if (err->type == AVDTP_ERROR_ERRNO)		return strerror(err->err.posix_errno);	switch(err->err.error_code) {	case AVDTP_BAD_HEADER_FORMAT:		return "Bad Header Format";	case AVDTP_BAD_LENGTH:		return "Bad Packet Lenght";	c

⌨️ 快捷键说明

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