107be7a6cSMaksim Yevmenkin /* 207be7a6cSMaksim Yevmenkin * sd.c 307be7a6cSMaksim Yevmenkin * 407be7a6cSMaksim Yevmenkin * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 507be7a6cSMaksim Yevmenkin * All rights reserved. 607be7a6cSMaksim Yevmenkin * 707be7a6cSMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without 807be7a6cSMaksim Yevmenkin * modification, are permitted provided that the following conditions 907be7a6cSMaksim Yevmenkin * are met: 1007be7a6cSMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright 1107be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer. 1207be7a6cSMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright 1307be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the 1407be7a6cSMaksim Yevmenkin * documentation and/or other materials provided with the distribution. 1507be7a6cSMaksim Yevmenkin * 1607be7a6cSMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1707be7a6cSMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1807be7a6cSMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1907be7a6cSMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2007be7a6cSMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2107be7a6cSMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2207be7a6cSMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2307be7a6cSMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2407be7a6cSMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2507be7a6cSMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2607be7a6cSMaksim Yevmenkin * SUCH DAMAGE. 2707be7a6cSMaksim Yevmenkin * 2807be7a6cSMaksim Yevmenkin * $Id: sd.c,v 1.4 2004/01/13 01:54:39 max Exp $ 2907be7a6cSMaksim Yevmenkin * $FreeBSD$ 3007be7a6cSMaksim Yevmenkin */ 3107be7a6cSMaksim Yevmenkin 3207be7a6cSMaksim Yevmenkin #include <sys/queue.h> 3307be7a6cSMaksim Yevmenkin #include <bluetooth.h> 3407be7a6cSMaksim Yevmenkin #include <sdp.h> 3507be7a6cSMaksim Yevmenkin #include <string.h> 3607be7a6cSMaksim Yevmenkin #include "profile.h" 3707be7a6cSMaksim Yevmenkin #include "provider.h" 3807be7a6cSMaksim Yevmenkin 3907be7a6cSMaksim Yevmenkin static int32_t 4007be7a6cSMaksim Yevmenkin sd_profile_create_service_class_id_list( 4107be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 4207be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 4307be7a6cSMaksim Yevmenkin { 4407be7a6cSMaksim Yevmenkin static uint16_t service_classes[] = { 4507be7a6cSMaksim Yevmenkin SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER 4607be7a6cSMaksim Yevmenkin }; 4707be7a6cSMaksim Yevmenkin 4807be7a6cSMaksim Yevmenkin return (common_profile_create_service_class_id_list( 4907be7a6cSMaksim Yevmenkin buf, eob, 5007be7a6cSMaksim Yevmenkin (uint8_t const *) service_classes, 5107be7a6cSMaksim Yevmenkin sizeof(service_classes))); 5207be7a6cSMaksim Yevmenkin } 5307be7a6cSMaksim Yevmenkin 5407be7a6cSMaksim Yevmenkin static int32_t 55c169089aSMaksim Yevmenkin sd_profile_create_bluetooth_profile_descriptor_list( 56c169089aSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 57c169089aSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 58c169089aSMaksim Yevmenkin { 59c169089aSMaksim Yevmenkin static uint16_t profile_descriptor_list[] = { 60c169089aSMaksim Yevmenkin SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, 61c169089aSMaksim Yevmenkin 0x0100 62c169089aSMaksim Yevmenkin }; 63c169089aSMaksim Yevmenkin 64c169089aSMaksim Yevmenkin return (common_profile_create_bluetooth_profile_descriptor_list( 65c169089aSMaksim Yevmenkin buf, eob, 66c169089aSMaksim Yevmenkin (uint8_t const *) profile_descriptor_list, 67c169089aSMaksim Yevmenkin sizeof(profile_descriptor_list))); 68c169089aSMaksim Yevmenkin } 69c169089aSMaksim Yevmenkin 70c169089aSMaksim Yevmenkin static int32_t 7107be7a6cSMaksim Yevmenkin sd_profile_create_service_id( 7207be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 7307be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 7407be7a6cSMaksim Yevmenkin { 7507be7a6cSMaksim Yevmenkin if (buf + 3 > eob) 7607be7a6cSMaksim Yevmenkin return (-1); 7707be7a6cSMaksim Yevmenkin 7807be7a6cSMaksim Yevmenkin /* 7907be7a6cSMaksim Yevmenkin * The ServiceID is a UUID that universally and uniquely identifies 8007be7a6cSMaksim Yevmenkin * the service instance described by the service record. This service 8107be7a6cSMaksim Yevmenkin * attribute is particularly useful if the same service is described 8207be7a6cSMaksim Yevmenkin * by service records in more than one SDP server 8307be7a6cSMaksim Yevmenkin */ 8407be7a6cSMaksim Yevmenkin 8507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 8607be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf); /* XXX ??? */ 8707be7a6cSMaksim Yevmenkin 8807be7a6cSMaksim Yevmenkin return (3); 8907be7a6cSMaksim Yevmenkin } 9007be7a6cSMaksim Yevmenkin 9107be7a6cSMaksim Yevmenkin static int32_t 9207be7a6cSMaksim Yevmenkin sd_profile_create_service_name( 9307be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 9407be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 9507be7a6cSMaksim Yevmenkin { 9607be7a6cSMaksim Yevmenkin static char service_name[] = "Bluetooth service discovery"; 9707be7a6cSMaksim Yevmenkin 9807be7a6cSMaksim Yevmenkin return (common_profile_create_string8( 9907be7a6cSMaksim Yevmenkin buf, eob, 10007be7a6cSMaksim Yevmenkin (uint8_t const *) service_name, strlen(service_name))); 10107be7a6cSMaksim Yevmenkin } 10207be7a6cSMaksim Yevmenkin 10307be7a6cSMaksim Yevmenkin static int32_t 10407be7a6cSMaksim Yevmenkin sd_profile_create_protocol_descriptor_list( 10507be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 10607be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 10707be7a6cSMaksim Yevmenkin { 108c169089aSMaksim Yevmenkin if (buf + 12 > eob) 10907be7a6cSMaksim Yevmenkin return (-1); 11007be7a6cSMaksim Yevmenkin 11107be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 112c169089aSMaksim Yevmenkin SDP_PUT8(10, buf); 11307be7a6cSMaksim Yevmenkin 11407be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 115c169089aSMaksim Yevmenkin SDP_PUT8(3, buf); 11607be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 11707be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); 11807be7a6cSMaksim Yevmenkin 119c169089aSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 120c169089aSMaksim Yevmenkin SDP_PUT8(3, buf); 121c169089aSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 122c169089aSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf); 12307be7a6cSMaksim Yevmenkin 124c169089aSMaksim Yevmenkin return (12); 12507be7a6cSMaksim Yevmenkin } 12607be7a6cSMaksim Yevmenkin 12707be7a6cSMaksim Yevmenkin static int32_t 12807be7a6cSMaksim Yevmenkin sd_profile_create_browse_group_list( 12907be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 13007be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 13107be7a6cSMaksim Yevmenkin { 13207be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 13307be7a6cSMaksim Yevmenkin return (-1); 13407be7a6cSMaksim Yevmenkin 13507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 13607be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf); 13707be7a6cSMaksim Yevmenkin 13807be7a6cSMaksim Yevmenkin /* 13907be7a6cSMaksim Yevmenkin * The top-level browse group ID, called PublicBrowseRoot and 14007be7a6cSMaksim Yevmenkin * representing the root of the browsing hierarchy, has the value 14107be7a6cSMaksim Yevmenkin * 00001002-0000-1000-8000-00805F9B34FB (UUID16: 0x1002) from the 14207be7a6cSMaksim Yevmenkin * Bluetooth Assigned Numbers document 14307be7a6cSMaksim Yevmenkin */ 14407be7a6cSMaksim Yevmenkin 14507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 14607be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, buf); 14707be7a6cSMaksim Yevmenkin 14807be7a6cSMaksim Yevmenkin return (5); 14907be7a6cSMaksim Yevmenkin } 15007be7a6cSMaksim Yevmenkin 15107be7a6cSMaksim Yevmenkin static int32_t 15207be7a6cSMaksim Yevmenkin sd_profile_create_version_number_list( 15307be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 15407be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 15507be7a6cSMaksim Yevmenkin { 15607be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 15707be7a6cSMaksim Yevmenkin return (-1); 15807be7a6cSMaksim Yevmenkin 15907be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 16007be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf); 16107be7a6cSMaksim Yevmenkin 16207be7a6cSMaksim Yevmenkin /* 16307be7a6cSMaksim Yevmenkin * The VersionNumberList is a data element sequence in which each 16407be7a6cSMaksim Yevmenkin * element of the sequence is a version number supported by the SDP 16507be7a6cSMaksim Yevmenkin * server. A version number is a 16-bit unsigned integer consisting 16607be7a6cSMaksim Yevmenkin * of two fields. The higher-order 8 bits contain the major version 16707be7a6cSMaksim Yevmenkin * number field and the low-order 8 bits contain the minor version 16807be7a6cSMaksim Yevmenkin * number field. The initial version of SDP has a major version of 16907be7a6cSMaksim Yevmenkin * 1 and a minor version of 0 17007be7a6cSMaksim Yevmenkin */ 17107be7a6cSMaksim Yevmenkin 17207be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf); 17307be7a6cSMaksim Yevmenkin SDP_PUT16(0x0100, buf); 17407be7a6cSMaksim Yevmenkin 17507be7a6cSMaksim Yevmenkin return (5); 17607be7a6cSMaksim Yevmenkin } 17707be7a6cSMaksim Yevmenkin 17807be7a6cSMaksim Yevmenkin static int32_t 17907be7a6cSMaksim Yevmenkin sd_profile_create_service_database_state( 18007be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 18107be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 18207be7a6cSMaksim Yevmenkin { 18307be7a6cSMaksim Yevmenkin uint32_t change_state = provider_get_change_state(); 18407be7a6cSMaksim Yevmenkin 18507be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 18607be7a6cSMaksim Yevmenkin return (-1); 18707be7a6cSMaksim Yevmenkin 18807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT32, buf); 18907be7a6cSMaksim Yevmenkin SDP_PUT32(change_state, buf); 19007be7a6cSMaksim Yevmenkin 19107be7a6cSMaksim Yevmenkin return (5); 19207be7a6cSMaksim Yevmenkin } 19307be7a6cSMaksim Yevmenkin 19407be7a6cSMaksim Yevmenkin static attr_t sd_profile_attrs[] = { 19507be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_RECORD_HANDLE, 19607be7a6cSMaksim Yevmenkin common_profile_create_service_record_handle }, 19707be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_CLASS_ID_LIST, 19807be7a6cSMaksim Yevmenkin sd_profile_create_service_class_id_list }, 199c169089aSMaksim Yevmenkin { SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, 200c169089aSMaksim Yevmenkin sd_profile_create_bluetooth_profile_descriptor_list }, 20107be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_ID, 20207be7a6cSMaksim Yevmenkin sd_profile_create_service_id }, 20307be7a6cSMaksim Yevmenkin { SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST, 20407be7a6cSMaksim Yevmenkin common_profile_create_language_base_attribute_id_list }, 20507be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, 20607be7a6cSMaksim Yevmenkin sd_profile_create_service_name }, 20707be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET, 20807be7a6cSMaksim Yevmenkin sd_profile_create_service_name }, 20907be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_PROVIDER_NAME_OFFSET, 21007be7a6cSMaksim Yevmenkin common_profile_create_service_provider_name }, 21107be7a6cSMaksim Yevmenkin { SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 21207be7a6cSMaksim Yevmenkin sd_profile_create_protocol_descriptor_list }, 21307be7a6cSMaksim Yevmenkin { SDP_ATTR_BROWSE_GROUP_LIST, 21407be7a6cSMaksim Yevmenkin sd_profile_create_browse_group_list }, 21507be7a6cSMaksim Yevmenkin { SDP_ATTR_VERSION_NUMBER_LIST, 21607be7a6cSMaksim Yevmenkin sd_profile_create_version_number_list }, 21707be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_DATABASE_STATE, 21807be7a6cSMaksim Yevmenkin sd_profile_create_service_database_state }, 21907be7a6cSMaksim Yevmenkin { 0, NULL } /* end entry */ 22007be7a6cSMaksim Yevmenkin }; 22107be7a6cSMaksim Yevmenkin 22207be7a6cSMaksim Yevmenkin profile_t sd_profile_descriptor = { 22307be7a6cSMaksim Yevmenkin SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, 22407be7a6cSMaksim Yevmenkin 0, 22507be7a6cSMaksim Yevmenkin (profile_data_valid_p) NULL, 22607be7a6cSMaksim Yevmenkin (attr_t const * const) &sd_profile_attrs 22707be7a6cSMaksim Yevmenkin }; 22807be7a6cSMaksim Yevmenkin 229