1 /* $NetBSD: hf.c,v 1.2 2007/11/09 20:08:40 plunky Exp $ */ 2 /* $DragonFly: src/usr.sbin/sdpd/hf.c,v 1.1 2008/01/06 21:51:30 hasso Exp $ */ 3 4 /*- 5 * Copyright (c) 2006 Itronix Inc. 6 * All rights reserved. 7 * 8 * Written by Iain Hibbert for Itronix Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of Itronix Inc. may not be used to endorse 19 * or promote products derived from this software without specific 20 * prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/queue.h> 36 #include <bluetooth.h> 37 #include <sdp.h> 38 #include <stdio.h> 39 #include <string.h> 40 41 #include <netbt/rfcomm.h> 42 43 #include "profile.h" 44 #include "provider.h" 45 46 static int32_t 47 hf_profile_create_service_class_id_list( 48 uint8_t *buf, uint8_t const * const eob, 49 uint8_t const *data, uint32_t datalen) 50 { 51 static uint16_t service_classes[] = { 52 SDP_SERVICE_CLASS_HANDSFREE, 53 SDP_SERVICE_CLASS_GENERIC_AUDIO, 54 }; 55 56 return (common_profile_create_service_class_id_list( 57 buf, eob, 58 (uint8_t const *) service_classes, 59 sizeof(service_classes))); 60 } 61 62 static int32_t 63 hf_profile_create_protocol_descriptor_list( 64 uint8_t *buf, uint8_t const * const eob, 65 uint8_t const *data, uint32_t datalen) 66 { 67 provider_t const *provider = (provider_t const *) data; 68 sdp_hf_profile_t *hf = (sdp_hf_profile_t *) provider->data; 69 70 return (rfcomm_profile_create_protocol_descriptor_list( 71 buf, eob, 72 (uint8_t const *) &hf->server_channel, 1)); 73 } 74 75 static int32_t 76 hf_profile_create_bluetooth_profile_descriptor_list( 77 uint8_t *buf, uint8_t const * const eob, 78 uint8_t const *data, uint32_t datalen) 79 { 80 static uint16_t profile_descriptor_list[] = { 81 SDP_SERVICE_CLASS_HANDSFREE, 82 0x0105 83 }; 84 85 return (common_profile_create_bluetooth_profile_descriptor_list( 86 buf, eob, 87 (uint8_t const *) profile_descriptor_list, 88 sizeof(profile_descriptor_list))); 89 } 90 91 static int32_t 92 hf_profile_create_service_name( 93 uint8_t *buf, uint8_t const * const eob, 94 uint8_t const *data, uint32_t datalen) 95 { 96 static char service_name[] = "Hands-Free unit"; 97 98 return (common_profile_create_string8( 99 buf, eob, 100 (uint8_t const *) service_name, strlen(service_name))); 101 } 102 103 static int32_t 104 hf_profile_create_supported_features( 105 uint8_t *buf, uint8_t const * const eob, 106 uint8_t const *data, uint32_t datalen) 107 { 108 provider_t const *provider = (provider_t const *) data; 109 sdp_hf_profile_t *hf = (sdp_hf_profile_t *) provider->data; 110 111 if (buf + 3 > eob) 112 return (-1); 113 114 SDP_PUT8(SDP_DATA_UINT16, buf); 115 SDP_PUT16(hf->supported_features, buf); 116 117 return (3); 118 } 119 120 static int32_t 121 hf_profile_data_valid(uint8_t const *data, uint32_t datalen) 122 { 123 sdp_hf_profile_t const *hf = (sdp_hf_profile_t const *) data; 124 125 if (hf->server_channel < RFCOMM_CHANNEL_MIN 126 || hf->server_channel > RFCOMM_CHANNEL_MAX 127 || (hf->supported_features & ~0x001f)) 128 return 0; 129 130 return 1; 131 } 132 133 static attr_t hf_profile_attrs[] = { 134 { SDP_ATTR_SERVICE_RECORD_HANDLE, 135 common_profile_create_service_record_handle }, 136 { SDP_ATTR_SERVICE_CLASS_ID_LIST, 137 hf_profile_create_service_class_id_list }, 138 { SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 139 hf_profile_create_protocol_descriptor_list }, 140 { SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, 141 hf_profile_create_bluetooth_profile_descriptor_list }, 142 { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, 143 hf_profile_create_service_name }, 144 { SDP_ATTR_SUPPORTED_FEATURES, 145 hf_profile_create_supported_features }, 146 { 0, NULL } /* end entry */ 147 }; 148 149 static uint16_t hf_profile_uuids[] = { 150 SDP_SERVICE_CLASS_HANDSFREE, 151 SDP_SERVICE_CLASS_GENERIC_AUDIO, 152 SDP_UUID_PROTOCOL_L2CAP, 153 SDP_UUID_PROTOCOL_RFCOMM, 154 }; 155 156 profile_t hf_profile_descriptor = { 157 hf_profile_uuids, 158 sizeof(hf_profile_uuids), 159 sizeof(sdp_hf_profile_t), 160 hf_profile_data_valid, 161 (attr_t const * const) &hf_profile_attrs 162 }; 163