1343572Shselasky/*-
2343572Shselasky * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3343572Shselasky *
4343572Shselasky * Copyright (c) 2019 Hans Petter Selasky <hselasky@freebsd.org>
5343572Shselasky * All rights reserved.
6343572Shselasky *
7343572Shselasky * Redistribution and use in source and binary forms, with or without
8343572Shselasky * modification, are permitted provided that the following conditions
9343572Shselasky * are met:
10343572Shselasky * 1. Redistributions of source code must retain the above copyright
11343572Shselasky *    notice, this list of conditions and the following disclaimer.
12343572Shselasky * 2. Redistributions in binary form must reproduce the above copyright
13343572Shselasky *    notice, this list of conditions and the following disclaimer in the
14343572Shselasky *    documentation and/or other materials provided with the distribution.
15343572Shselasky *
16343572Shselasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17343572Shselasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18343572Shselasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19343572Shselasky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20343572Shselasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21343572Shselasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22343572Shselasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23343572Shselasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24343572Shselasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25343572Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26343572Shselasky * SUCH DAMAGE.
27343572Shselasky *
28343572Shselasky * $FreeBSD: stable/10/usr.sbin/bluetooth/sdpd/audio_source.c 343902 2019-02-08 10:28:13Z hselasky $
29343572Shselasky */
30343572Shselasky
31343572Shselasky#include <sys/queue.h>
32343572Shselasky#define	L2CAP_SOCKET_CHECKED
33343572Shselasky#include <bluetooth.h>
34343572Shselasky#include <sdp.h>
35343572Shselasky#include <string.h>
36343572Shselasky#include "profile.h"
37343572Shselasky#include "provider.h"
38343572Shselasky
39343572Shselaskystatic int32_t
40343572Shselaskyaudio_source_profile_create_service_class_id_list(
41343572Shselasky    uint8_t *buf, uint8_t const *const eob,
42343572Shselasky    uint8_t const *data, uint32_t datalen)
43343572Shselasky{
44343572Shselasky	static const uint16_t service_classes[] = {
45343572Shselasky		SDP_SERVICE_CLASS_AUDIO_SOURCE,
46343572Shselasky	};
47343572Shselasky
48343572Shselasky	return (common_profile_create_service_class_id_list(
49343572Shselasky	    buf, eob,
50343572Shselasky	    (uint8_t const *)service_classes,
51343572Shselasky	    sizeof(service_classes)));
52343572Shselasky}
53343572Shselasky
54343572Shselaskystatic int32_t
55343572Shselaskyaudio_source_profile_create_protocol_descriptor_list(
56343572Shselasky    uint8_t *buf, uint8_t const *const eob,
57343572Shselasky    uint8_t const *data, uint32_t datalen)
58343572Shselasky{
59343572Shselasky	provider_p provider = (provider_p) data;
60343572Shselasky	sdp_audio_source_profile_p audio_source = (sdp_audio_source_profile_p) provider->data;
61343572Shselasky
62343572Shselasky	if (buf + 18 > eob)
63343572Shselasky		return (-1);
64343572Shselasky
65343572Shselasky	SDP_PUT8(SDP_DATA_SEQ8, buf);
66343572Shselasky	SDP_PUT8(16, buf);
67343572Shselasky
68343572Shselasky	SDP_PUT8(SDP_DATA_SEQ8, buf);
69343572Shselasky	SDP_PUT8(6, buf);
70343572Shselasky
71343572Shselasky	SDP_PUT8(SDP_DATA_UUID16, buf);
72343572Shselasky	SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
73343572Shselasky
74343572Shselasky	SDP_PUT8(SDP_DATA_UINT16, buf);
75343572Shselasky	SDP_PUT16(audio_source->psm, buf);
76343572Shselasky
77343572Shselasky	SDP_PUT8(SDP_DATA_SEQ8, buf);
78343572Shselasky	SDP_PUT8(6, buf);
79343572Shselasky
80343572Shselasky	SDP_PUT8(SDP_DATA_UUID16, buf);
81343572Shselasky	SDP_PUT16(SDP_UUID_PROTOCOL_AVDTP, buf);
82343572Shselasky
83343572Shselasky	SDP_PUT8(SDP_DATA_UINT16, buf);
84343572Shselasky	SDP_PUT16(audio_source->protover, buf);
85343572Shselasky
86343572Shselasky	return (18);
87343572Shselasky}
88343572Shselasky
89343572Shselaskystatic int32_t
90343572Shselaskyaudio_source_profile_create_browse_group_list(
91343572Shselasky    uint8_t *buf, uint8_t const *const eob,
92343572Shselasky    uint8_t const *data, uint32_t datalen)
93343572Shselasky{
94343572Shselasky
95343572Shselasky	if (buf + 5 > eob)
96343572Shselasky		return (-1);
97343572Shselasky
98343572Shselasky	SDP_PUT8(SDP_DATA_SEQ8, buf);
99343572Shselasky	SDP_PUT8(3, buf);
100343572Shselasky
101343572Shselasky	SDP_PUT8(SDP_DATA_UUID16, buf);
102343572Shselasky	SDP_PUT16(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, buf);
103343572Shselasky
104343572Shselasky	return (5);
105343572Shselasky}
106343572Shselasky
107343572Shselaskystatic int32_t
108343572Shselaskyaudio_source_profile_create_bluetooth_profile_descriptor_list(
109343572Shselasky    uint8_t *buf, uint8_t const *const eob,
110343572Shselasky    uint8_t const *data, uint32_t datalen)
111343572Shselasky{
112343572Shselasky	static const uint16_t profile_descriptor_list[] = {
113343572Shselasky		SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION,
114343572Shselasky		0x0100
115343572Shselasky	};
116343572Shselasky
117343572Shselasky	return (common_profile_create_bluetooth_profile_descriptor_list(
118343572Shselasky	    buf, eob,
119343572Shselasky	    (uint8_t const *)profile_descriptor_list,
120343572Shselasky	    sizeof(profile_descriptor_list)));
121343572Shselasky}
122343572Shselasky
123343572Shselaskystatic int32_t
124343572Shselaskyaudio_source_profile_create_service_name(
125343572Shselasky    uint8_t *buf, uint8_t const *const eob,
126343572Shselasky    uint8_t const *data, uint32_t datalen)
127343572Shselasky{
128343572Shselasky	static const char service_name[] = "Audio SRC";
129343572Shselasky
130343572Shselasky	return (common_profile_create_string8(
131343572Shselasky	    buf, eob,
132343572Shselasky	    (uint8_t const *)service_name, strlen(service_name)));
133343572Shselasky}
134343572Shselasky
135343572Shselaskystatic int32_t
136343572Shselaskyaudio_source_create_supported_features(
137343572Shselasky    uint8_t *buf, uint8_t const *const eob,
138343572Shselasky    uint8_t const *data, uint32_t datalen)
139343572Shselasky{
140343572Shselasky	provider_p provider = (provider_p) data;
141343572Shselasky	sdp_audio_source_profile_p audio_source = (sdp_audio_source_profile_p) provider->data;
142343572Shselasky
143343572Shselasky	if (buf + 3 > eob)
144343572Shselasky		return (-1);
145343572Shselasky
146343572Shselasky	SDP_PUT8(SDP_DATA_UINT16, buf);
147343572Shselasky	SDP_PUT16(audio_source->features, buf);
148343572Shselasky
149343572Shselasky	return (3);
150343572Shselasky}
151343572Shselasky
152343572Shselaskystatic int32_t
153343572Shselaskyaudio_source_profile_valid(uint8_t const *data, uint32_t datalen)
154343572Shselasky{
155343572Shselasky
156343572Shselasky	if (datalen < sizeof(struct sdp_audio_source_profile))
157343572Shselasky		return (0);
158343572Shselasky	return (1);
159343572Shselasky}
160343572Shselasky
161343572Shselaskystatic const attr_t audio_source_profile_attrs[] = {
162343572Shselasky	{SDP_ATTR_SERVICE_RECORD_HANDLE,
163343572Shselasky	common_profile_create_service_record_handle},
164343572Shselasky	{SDP_ATTR_SERVICE_CLASS_ID_LIST,
165343572Shselasky	audio_source_profile_create_service_class_id_list},
166343572Shselasky	{SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
167343572Shselasky	audio_source_profile_create_protocol_descriptor_list},
168343572Shselasky	{SDP_ATTR_BROWSE_GROUP_LIST,
169343572Shselasky	audio_source_profile_create_browse_group_list},
170343572Shselasky	{SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST,
171343572Shselasky	common_profile_create_language_base_attribute_id_list},
172343572Shselasky	{SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
173343572Shselasky	audio_source_profile_create_bluetooth_profile_descriptor_list},
174343572Shselasky	{SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET,
175343572Shselasky	audio_source_profile_create_service_name},
176343572Shselasky	{SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_PROVIDER_NAME_OFFSET,
177343572Shselasky	common_profile_create_service_provider_name},
178343572Shselasky	{SDP_ATTR_SUPPORTED_FEATURES,
179343572Shselasky	audio_source_create_supported_features},
180343572Shselasky	{}				/* end entry */
181343572Shselasky};
182343572Shselasky
183343572Shselaskyprofile_t audio_source_profile_descriptor = {
184343572Shselasky	SDP_SERVICE_CLASS_AUDIO_SOURCE,
185343572Shselasky	sizeof(sdp_audio_source_profile_t),
186343572Shselasky	audio_source_profile_valid,
187343572Shselasky	(attr_t const *const)&audio_source_profile_attrs
188343572Shselasky};
189