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_sink.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_sink_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_SINK, 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_sink_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_sink_profile_p audio_sink = (sdp_audio_sink_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_sink->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_sink->protover, buf); 85343572Shselasky 86343572Shselasky return (18); 87343572Shselasky} 88343572Shselasky 89343572Shselaskystatic int32_t 90343572Shselaskyaudio_sink_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_sink_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_sink_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 SNK"; 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_sink_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_sink_profile_p audio_sink = (sdp_audio_sink_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_sink->features, buf); 148343572Shselasky 149343572Shselasky return (3); 150343572Shselasky} 151343572Shselasky 152343572Shselaskystatic int32_t 153343572Shselaskyaudio_sink_profile_valid(uint8_t const *data, uint32_t datalen) 154343572Shselasky{ 155343572Shselasky 156343572Shselasky if (datalen < sizeof(struct sdp_audio_sink_profile)) 157343572Shselasky return (0); 158343572Shselasky return (1); 159343572Shselasky} 160343572Shselasky 161343572Shselaskystatic const attr_t audio_sink_profile_attrs[] = { 162343572Shselasky {SDP_ATTR_SERVICE_RECORD_HANDLE, 163343572Shselasky common_profile_create_service_record_handle}, 164343572Shselasky {SDP_ATTR_SERVICE_CLASS_ID_LIST, 165343572Shselasky audio_sink_profile_create_service_class_id_list}, 166343572Shselasky {SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 167343572Shselasky audio_sink_profile_create_protocol_descriptor_list}, 168343572Shselasky {SDP_ATTR_BROWSE_GROUP_LIST, 169343572Shselasky audio_sink_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_sink_profile_create_bluetooth_profile_descriptor_list}, 174343572Shselasky {SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, 175343572Shselasky audio_sink_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_sink_create_supported_features}, 180343572Shselasky {} /* end entry */ 181343572Shselasky}; 182343572Shselasky 183343572Shselaskyprofile_t audio_sink_profile_descriptor = { 184343572Shselasky SDP_SERVICE_CLASS_AUDIO_SINK, 185343572Shselasky sizeof(sdp_audio_sink_profile_t), 186343572Shselasky audio_sink_profile_valid, 187343572Shselasky (attr_t const *const)&audio_sink_profile_attrs 188343572Shselasky}; 189