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 5507be7a6cSMaksim Yevmenkin sd_profile_create_service_id( 5607be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 5707be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 5807be7a6cSMaksim Yevmenkin { 5907be7a6cSMaksim Yevmenkin if (buf + 3 > eob) 6007be7a6cSMaksim Yevmenkin return (-1); 6107be7a6cSMaksim Yevmenkin 6207be7a6cSMaksim Yevmenkin /* 6307be7a6cSMaksim Yevmenkin * The ServiceID is a UUID that universally and uniquely identifies 6407be7a6cSMaksim Yevmenkin * the service instance described by the service record. This service 6507be7a6cSMaksim Yevmenkin * attribute is particularly useful if the same service is described 6607be7a6cSMaksim Yevmenkin * by service records in more than one SDP server 6707be7a6cSMaksim Yevmenkin */ 6807be7a6cSMaksim Yevmenkin 6907be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 7007be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf); /* XXX ??? */ 7107be7a6cSMaksim Yevmenkin 7207be7a6cSMaksim Yevmenkin return (3); 7307be7a6cSMaksim Yevmenkin } 7407be7a6cSMaksim Yevmenkin 7507be7a6cSMaksim Yevmenkin static int32_t 7607be7a6cSMaksim Yevmenkin sd_profile_create_service_name( 7707be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 7807be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 7907be7a6cSMaksim Yevmenkin { 8007be7a6cSMaksim Yevmenkin static char service_name[] = "Bluetooth service discovery"; 8107be7a6cSMaksim Yevmenkin 8207be7a6cSMaksim Yevmenkin return (common_profile_create_string8( 8307be7a6cSMaksim Yevmenkin buf, eob, 8407be7a6cSMaksim Yevmenkin (uint8_t const *) service_name, strlen(service_name))); 8507be7a6cSMaksim Yevmenkin } 8607be7a6cSMaksim Yevmenkin 8707be7a6cSMaksim Yevmenkin static int32_t 8807be7a6cSMaksim Yevmenkin sd_profile_create_protocol_descriptor_list( 8907be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 9007be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 9107be7a6cSMaksim Yevmenkin { 9207be7a6cSMaksim Yevmenkin if (buf + 13 > eob) 9307be7a6cSMaksim Yevmenkin return (-1); 9407be7a6cSMaksim Yevmenkin 9507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 9607be7a6cSMaksim Yevmenkin SDP_PUT8(11, buf); 9707be7a6cSMaksim Yevmenkin 9807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 9907be7a6cSMaksim Yevmenkin SDP_PUT8(9, buf); 10007be7a6cSMaksim Yevmenkin 10107be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 10207be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); 10307be7a6cSMaksim Yevmenkin 10407be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf); 10507be7a6cSMaksim Yevmenkin SDP_PUT16(NG_L2CAP_PSM_SDP, buf); 10607be7a6cSMaksim Yevmenkin 10707be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf); 10807be7a6cSMaksim Yevmenkin SDP_PUT16(1, buf); /* version */ 10907be7a6cSMaksim Yevmenkin 11007be7a6cSMaksim Yevmenkin return (13); 11107be7a6cSMaksim Yevmenkin } 11207be7a6cSMaksim Yevmenkin 11307be7a6cSMaksim Yevmenkin static int32_t 11407be7a6cSMaksim Yevmenkin sd_profile_create_browse_group_list( 11507be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 11607be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 11707be7a6cSMaksim Yevmenkin { 11807be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 11907be7a6cSMaksim Yevmenkin return (-1); 12007be7a6cSMaksim Yevmenkin 12107be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 12207be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf); 12307be7a6cSMaksim Yevmenkin 12407be7a6cSMaksim Yevmenkin /* 12507be7a6cSMaksim Yevmenkin * The top-level browse group ID, called PublicBrowseRoot and 12607be7a6cSMaksim Yevmenkin * representing the root of the browsing hierarchy, has the value 12707be7a6cSMaksim Yevmenkin * 00001002-0000-1000-8000-00805F9B34FB (UUID16: 0x1002) from the 12807be7a6cSMaksim Yevmenkin * Bluetooth Assigned Numbers document 12907be7a6cSMaksim Yevmenkin */ 13007be7a6cSMaksim Yevmenkin 13107be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 13207be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, buf); 13307be7a6cSMaksim Yevmenkin 13407be7a6cSMaksim Yevmenkin return (5); 13507be7a6cSMaksim Yevmenkin } 13607be7a6cSMaksim Yevmenkin 13707be7a6cSMaksim Yevmenkin static int32_t 13807be7a6cSMaksim Yevmenkin sd_profile_create_version_number_list( 13907be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 14007be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 14107be7a6cSMaksim Yevmenkin { 14207be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 14307be7a6cSMaksim Yevmenkin return (-1); 14407be7a6cSMaksim Yevmenkin 14507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 14607be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf); 14707be7a6cSMaksim Yevmenkin 14807be7a6cSMaksim Yevmenkin /* 14907be7a6cSMaksim Yevmenkin * The VersionNumberList is a data element sequence in which each 15007be7a6cSMaksim Yevmenkin * element of the sequence is a version number supported by the SDP 15107be7a6cSMaksim Yevmenkin * server. A version number is a 16-bit unsigned integer consisting 15207be7a6cSMaksim Yevmenkin * of two fields. The higher-order 8 bits contain the major version 15307be7a6cSMaksim Yevmenkin * number field and the low-order 8 bits contain the minor version 15407be7a6cSMaksim Yevmenkin * number field. The initial version of SDP has a major version of 15507be7a6cSMaksim Yevmenkin * 1 and a minor version of 0 15607be7a6cSMaksim Yevmenkin */ 15707be7a6cSMaksim Yevmenkin 15807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf); 15907be7a6cSMaksim Yevmenkin SDP_PUT16(0x0100, buf); 16007be7a6cSMaksim Yevmenkin 16107be7a6cSMaksim Yevmenkin return (5); 16207be7a6cSMaksim Yevmenkin } 16307be7a6cSMaksim Yevmenkin 16407be7a6cSMaksim Yevmenkin static int32_t 16507be7a6cSMaksim Yevmenkin sd_profile_create_service_database_state( 16607be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 16707be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 16807be7a6cSMaksim Yevmenkin { 16907be7a6cSMaksim Yevmenkin uint32_t change_state = provider_get_change_state(); 17007be7a6cSMaksim Yevmenkin 17107be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 17207be7a6cSMaksim Yevmenkin return (-1); 17307be7a6cSMaksim Yevmenkin 17407be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT32, buf); 17507be7a6cSMaksim Yevmenkin SDP_PUT32(change_state, buf); 17607be7a6cSMaksim Yevmenkin 17707be7a6cSMaksim Yevmenkin return (5); 17807be7a6cSMaksim Yevmenkin } 17907be7a6cSMaksim Yevmenkin 18007be7a6cSMaksim Yevmenkin static attr_t sd_profile_attrs[] = { 18107be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_RECORD_HANDLE, 18207be7a6cSMaksim Yevmenkin common_profile_create_service_record_handle }, 18307be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_CLASS_ID_LIST, 18407be7a6cSMaksim Yevmenkin sd_profile_create_service_class_id_list }, 18507be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_ID, 18607be7a6cSMaksim Yevmenkin sd_profile_create_service_id }, 18707be7a6cSMaksim Yevmenkin { SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST, 18807be7a6cSMaksim Yevmenkin common_profile_create_language_base_attribute_id_list }, 18907be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, 19007be7a6cSMaksim Yevmenkin sd_profile_create_service_name }, 19107be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET, 19207be7a6cSMaksim Yevmenkin sd_profile_create_service_name }, 19307be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_PROVIDER_NAME_OFFSET, 19407be7a6cSMaksim Yevmenkin common_profile_create_service_provider_name }, 19507be7a6cSMaksim Yevmenkin { SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 19607be7a6cSMaksim Yevmenkin sd_profile_create_protocol_descriptor_list }, 19707be7a6cSMaksim Yevmenkin { SDP_ATTR_BROWSE_GROUP_LIST, 19807be7a6cSMaksim Yevmenkin sd_profile_create_browse_group_list }, 19907be7a6cSMaksim Yevmenkin { SDP_ATTR_VERSION_NUMBER_LIST, 20007be7a6cSMaksim Yevmenkin sd_profile_create_version_number_list }, 20107be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_DATABASE_STATE, 20207be7a6cSMaksim Yevmenkin sd_profile_create_service_database_state }, 20307be7a6cSMaksim Yevmenkin { 0, NULL } /* end entry */ 20407be7a6cSMaksim Yevmenkin }; 20507be7a6cSMaksim Yevmenkin 20607be7a6cSMaksim Yevmenkin profile_t sd_profile_descriptor = { 20707be7a6cSMaksim Yevmenkin SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, 20807be7a6cSMaksim Yevmenkin 0, 20907be7a6cSMaksim Yevmenkin (profile_data_valid_p) NULL, 21007be7a6cSMaksim Yevmenkin (attr_t const * const) &sd_profile_attrs 21107be7a6cSMaksim Yevmenkin }; 21207be7a6cSMaksim Yevmenkin 213