121be80aeSHans Petter Selasky /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 321be80aeSHans Petter Selasky * 421be80aeSHans Petter Selasky * Copyright (c) 2019 Hans Petter Selasky <hselasky@freebsd.org> 521be80aeSHans Petter Selasky * All rights reserved. 621be80aeSHans Petter Selasky * 721be80aeSHans Petter Selasky * Redistribution and use in source and binary forms, with or without 821be80aeSHans Petter Selasky * modification, are permitted provided that the following conditions 921be80aeSHans Petter Selasky * are met: 1021be80aeSHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 1121be80aeSHans Petter Selasky * notice, this list of conditions and the following disclaimer. 1221be80aeSHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 1321be80aeSHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 1421be80aeSHans Petter Selasky * documentation and/or other materials provided with the distribution. 1521be80aeSHans Petter Selasky * 1621be80aeSHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1721be80aeSHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1821be80aeSHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1921be80aeSHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2021be80aeSHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2121be80aeSHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2221be80aeSHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2321be80aeSHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2421be80aeSHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2521be80aeSHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2621be80aeSHans Petter Selasky * SUCH DAMAGE. 2721be80aeSHans Petter Selasky * 2821be80aeSHans Petter Selasky * $FreeBSD$ 2921be80aeSHans Petter Selasky */ 3021be80aeSHans Petter Selasky 3121be80aeSHans Petter Selasky #include <sys/queue.h> 3221be80aeSHans Petter Selasky #define L2CAP_SOCKET_CHECKED 3321be80aeSHans Petter Selasky #include <bluetooth.h> 3421be80aeSHans Petter Selasky #include <sdp.h> 3521be80aeSHans Petter Selasky #include <string.h> 3621be80aeSHans Petter Selasky #include "profile.h" 3721be80aeSHans Petter Selasky #include "provider.h" 3821be80aeSHans Petter Selasky 3921be80aeSHans Petter Selasky static int32_t 4021be80aeSHans Petter Selasky audio_source_profile_create_service_class_id_list( 4121be80aeSHans Petter Selasky uint8_t *buf, uint8_t const *const eob, 4221be80aeSHans Petter Selasky uint8_t const *data, uint32_t datalen) 4321be80aeSHans Petter Selasky { 4421be80aeSHans Petter Selasky static const uint16_t service_classes[] = { 4521be80aeSHans Petter Selasky SDP_SERVICE_CLASS_AUDIO_SOURCE, 4621be80aeSHans Petter Selasky }; 4721be80aeSHans Petter Selasky 4821be80aeSHans Petter Selasky return (common_profile_create_service_class_id_list( 4921be80aeSHans Petter Selasky buf, eob, 5021be80aeSHans Petter Selasky (uint8_t const *)service_classes, 5121be80aeSHans Petter Selasky sizeof(service_classes))); 5221be80aeSHans Petter Selasky } 5321be80aeSHans Petter Selasky 5421be80aeSHans Petter Selasky static int32_t 5521be80aeSHans Petter Selasky audio_source_profile_create_protocol_descriptor_list( 5621be80aeSHans Petter Selasky uint8_t *buf, uint8_t const *const eob, 5721be80aeSHans Petter Selasky uint8_t const *data, uint32_t datalen) 5821be80aeSHans Petter Selasky { 5921be80aeSHans Petter Selasky provider_p provider = (provider_p) data; 6021be80aeSHans Petter Selasky sdp_audio_source_profile_p audio_source = (sdp_audio_source_profile_p) provider->data; 6121be80aeSHans Petter Selasky 6221be80aeSHans Petter Selasky if (buf + 18 > eob) 6321be80aeSHans Petter Selasky return (-1); 6421be80aeSHans Petter Selasky 6521be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_SEQ8, buf); 6621be80aeSHans Petter Selasky SDP_PUT8(16, buf); 6721be80aeSHans Petter Selasky 6821be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_SEQ8, buf); 6921be80aeSHans Petter Selasky SDP_PUT8(6, buf); 7021be80aeSHans Petter Selasky 7121be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_UUID16, buf); 7221be80aeSHans Petter Selasky SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); 7321be80aeSHans Petter Selasky 7421be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_UINT16, buf); 7521be80aeSHans Petter Selasky SDP_PUT16(audio_source->psm, buf); 7621be80aeSHans Petter Selasky 7721be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_SEQ8, buf); 7821be80aeSHans Petter Selasky SDP_PUT8(6, buf); 7921be80aeSHans Petter Selasky 8021be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_UUID16, buf); 8121be80aeSHans Petter Selasky SDP_PUT16(SDP_UUID_PROTOCOL_AVDTP, buf); 8221be80aeSHans Petter Selasky 8321be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_UINT16, buf); 8421be80aeSHans Petter Selasky SDP_PUT16(audio_source->protover, buf); 8521be80aeSHans Petter Selasky 8621be80aeSHans Petter Selasky return (18); 8721be80aeSHans Petter Selasky } 8821be80aeSHans Petter Selasky 8921be80aeSHans Petter Selasky static int32_t 9021be80aeSHans Petter Selasky audio_source_profile_create_browse_group_list( 9121be80aeSHans Petter Selasky uint8_t *buf, uint8_t const *const eob, 9221be80aeSHans Petter Selasky uint8_t const *data, uint32_t datalen) 9321be80aeSHans Petter Selasky { 9421be80aeSHans Petter Selasky 9521be80aeSHans Petter Selasky if (buf + 5 > eob) 9621be80aeSHans Petter Selasky return (-1); 9721be80aeSHans Petter Selasky 9821be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_SEQ8, buf); 9921be80aeSHans Petter Selasky SDP_PUT8(3, buf); 10021be80aeSHans Petter Selasky 10121be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_UUID16, buf); 10221be80aeSHans Petter Selasky SDP_PUT16(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, buf); 10321be80aeSHans Petter Selasky 10421be80aeSHans Petter Selasky return (5); 10521be80aeSHans Petter Selasky } 10621be80aeSHans Petter Selasky 10721be80aeSHans Petter Selasky static int32_t 10821be80aeSHans Petter Selasky audio_source_profile_create_bluetooth_profile_descriptor_list( 10921be80aeSHans Petter Selasky uint8_t *buf, uint8_t const *const eob, 11021be80aeSHans Petter Selasky uint8_t const *data, uint32_t datalen) 11121be80aeSHans Petter Selasky { 11221be80aeSHans Petter Selasky static const uint16_t profile_descriptor_list[] = { 11321be80aeSHans Petter Selasky SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION, 11421be80aeSHans Petter Selasky 0x0100 11521be80aeSHans Petter Selasky }; 11621be80aeSHans Petter Selasky 11721be80aeSHans Petter Selasky return (common_profile_create_bluetooth_profile_descriptor_list( 11821be80aeSHans Petter Selasky buf, eob, 11921be80aeSHans Petter Selasky (uint8_t const *)profile_descriptor_list, 12021be80aeSHans Petter Selasky sizeof(profile_descriptor_list))); 12121be80aeSHans Petter Selasky } 12221be80aeSHans Petter Selasky 12321be80aeSHans Petter Selasky static int32_t 12421be80aeSHans Petter Selasky audio_source_profile_create_service_name( 12521be80aeSHans Petter Selasky uint8_t *buf, uint8_t const *const eob, 12621be80aeSHans Petter Selasky uint8_t const *data, uint32_t datalen) 12721be80aeSHans Petter Selasky { 12821be80aeSHans Petter Selasky static const char service_name[] = "Audio SRC"; 12921be80aeSHans Petter Selasky 13021be80aeSHans Petter Selasky return (common_profile_create_string8( 13121be80aeSHans Petter Selasky buf, eob, 13221be80aeSHans Petter Selasky (uint8_t const *)service_name, strlen(service_name))); 13321be80aeSHans Petter Selasky } 13421be80aeSHans Petter Selasky 13521be80aeSHans Petter Selasky static int32_t 13621be80aeSHans Petter Selasky audio_source_create_supported_features( 13721be80aeSHans Petter Selasky uint8_t *buf, uint8_t const *const eob, 13821be80aeSHans Petter Selasky uint8_t const *data, uint32_t datalen) 13921be80aeSHans Petter Selasky { 14021be80aeSHans Petter Selasky provider_p provider = (provider_p) data; 14121be80aeSHans Petter Selasky sdp_audio_source_profile_p audio_source = (sdp_audio_source_profile_p) provider->data; 14221be80aeSHans Petter Selasky 14321be80aeSHans Petter Selasky if (buf + 3 > eob) 14421be80aeSHans Petter Selasky return (-1); 14521be80aeSHans Petter Selasky 14621be80aeSHans Petter Selasky SDP_PUT8(SDP_DATA_UINT16, buf); 14721be80aeSHans Petter Selasky SDP_PUT16(audio_source->features, buf); 14821be80aeSHans Petter Selasky 14921be80aeSHans Petter Selasky return (3); 15021be80aeSHans Petter Selasky } 15121be80aeSHans Petter Selasky 15221be80aeSHans Petter Selasky static int32_t 15321be80aeSHans Petter Selasky audio_source_profile_valid(uint8_t const *data, uint32_t datalen) 15421be80aeSHans Petter Selasky { 15521be80aeSHans Petter Selasky 15621be80aeSHans Petter Selasky if (datalen < sizeof(struct sdp_audio_source_profile)) 15721be80aeSHans Petter Selasky return (0); 15821be80aeSHans Petter Selasky return (1); 15921be80aeSHans Petter Selasky } 16021be80aeSHans Petter Selasky 16121be80aeSHans Petter Selasky static const attr_t audio_source_profile_attrs[] = { 16221be80aeSHans Petter Selasky {SDP_ATTR_SERVICE_RECORD_HANDLE, 16321be80aeSHans Petter Selasky common_profile_create_service_record_handle}, 16421be80aeSHans Petter Selasky {SDP_ATTR_SERVICE_CLASS_ID_LIST, 16521be80aeSHans Petter Selasky audio_source_profile_create_service_class_id_list}, 16621be80aeSHans Petter Selasky {SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 16721be80aeSHans Petter Selasky audio_source_profile_create_protocol_descriptor_list}, 16821be80aeSHans Petter Selasky {SDP_ATTR_BROWSE_GROUP_LIST, 16921be80aeSHans Petter Selasky audio_source_profile_create_browse_group_list}, 17021be80aeSHans Petter Selasky {SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST, 17121be80aeSHans Petter Selasky common_profile_create_language_base_attribute_id_list}, 17221be80aeSHans Petter Selasky {SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, 17321be80aeSHans Petter Selasky audio_source_profile_create_bluetooth_profile_descriptor_list}, 17421be80aeSHans Petter Selasky {SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, 17521be80aeSHans Petter Selasky audio_source_profile_create_service_name}, 17621be80aeSHans Petter Selasky {SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_PROVIDER_NAME_OFFSET, 17721be80aeSHans Petter Selasky common_profile_create_service_provider_name}, 17821be80aeSHans Petter Selasky {SDP_ATTR_SUPPORTED_FEATURES, 17921be80aeSHans Petter Selasky audio_source_create_supported_features}, 18021be80aeSHans Petter Selasky {} /* end entry */ 18121be80aeSHans Petter Selasky }; 18221be80aeSHans Petter Selasky 18321be80aeSHans Petter Selasky profile_t audio_source_profile_descriptor = { 18421be80aeSHans Petter Selasky SDP_SERVICE_CLASS_AUDIO_SOURCE, 18521be80aeSHans Petter Selasky sizeof(sdp_audio_source_profile_t), 18621be80aeSHans Petter Selasky audio_source_profile_valid, 18721be80aeSHans Petter Selasky (attr_t const *const)&audio_source_profile_attrs 18821be80aeSHans Petter Selasky }; 189