1 /* 2 * provider.c 3 * 4 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id: provider.c,v 1.5 2004/01/13 01:54:39 max Exp $ 29 * $FreeBSD$ 30 */ 31 32 #include <sys/queue.h> 33 #include <bluetooth.h> 34 #include <string.h> 35 #include <stdlib.h> 36 #include "profile.h" 37 #include "provider.h" 38 39 static TAILQ_HEAD(, provider) providers = TAILQ_HEAD_INITIALIZER(providers); 40 static uint32_t change_state = 0; 41 static uint32_t handle = 0; 42 43 /* 44 * Register Service Discovery provider. 45 * Should not be called more the once. 46 */ 47 48 int32_t 49 provider_register_sd(int32_t fd) 50 { 51 extern profile_t sd_profile_descriptor; 52 extern profile_t bgd_profile_descriptor; 53 54 provider_p sd = calloc(1, sizeof(*sd)); 55 provider_p bgd = calloc(1, sizeof(*bgd)); 56 57 if (sd == NULL || bgd == NULL) { 58 if (sd != NULL) 59 free(sd); 60 61 if (bgd != NULL) 62 free(bgd); 63 64 return (-1); 65 } 66 67 sd->profile = &sd_profile_descriptor; 68 bgd->handle = 0; 69 sd->fd = fd; 70 TAILQ_INSERT_HEAD(&providers, sd, provider_next); 71 72 bgd->profile = &bgd_profile_descriptor; 73 bgd->handle = 1; 74 sd->fd = fd; 75 TAILQ_INSERT_AFTER(&providers, sd, bgd, provider_next); 76 77 change_state ++; 78 79 return (0); 80 } 81 82 /* 83 * Register new provider for a given profile, bdaddr and session. 84 */ 85 86 provider_p 87 provider_register(profile_p const profile, bdaddr_p const bdaddr, int32_t fd, 88 uint8_t const *data, uint32_t datalen) 89 { 90 provider_p provider = calloc(1, sizeof(*provider)); 91 92 if (provider != NULL) { 93 provider->data = malloc(datalen); 94 if (provider->data != NULL) { 95 provider->profile = profile; 96 memcpy(provider->data, data, datalen); 97 98 /* 99 * Record handles 0x0 and 0x1 are reserved 100 * for SDP itself 101 */ 102 103 if (++ handle <= 1) 104 handle = 2; 105 106 provider->handle = handle; 107 108 memcpy(&provider->bdaddr, bdaddr, 109 sizeof(provider->bdaddr)); 110 provider->fd = fd; 111 112 TAILQ_INSERT_TAIL(&providers, provider, provider_next); 113 change_state ++; 114 } else { 115 free(provider); 116 provider = NULL; 117 } 118 } 119 120 return (provider); 121 } 122 123 /* 124 * Unregister provider 125 */ 126 127 void 128 provider_unregister(provider_p provider) 129 { 130 TAILQ_REMOVE(&providers, provider, provider_next); 131 if (provider->data != NULL) 132 free(provider->data); 133 free(provider); 134 change_state ++; 135 } 136 137 /* 138 * Update provider data 139 */ 140 141 int32_t 142 provider_update(provider_p provider, uint8_t const *data, uint32_t datalen) 143 { 144 uint8_t *new_data = (uint8_t *) realloc(provider->data, datalen); 145 146 if (new_data == NULL) 147 return (-1); 148 149 memcpy(new_data, data, datalen); 150 provider->data = new_data; 151 152 return (0); 153 } 154 155 /* 156 * Get a provider for given record handle 157 */ 158 159 provider_p 160 provider_by_handle(uint32_t handle) 161 { 162 provider_p provider = NULL; 163 164 TAILQ_FOREACH(provider, &providers, provider_next) 165 if (provider->handle == handle) 166 break; 167 168 return (provider); 169 } 170 171 /* 172 * Cursor access 173 */ 174 175 provider_p 176 provider_get_first(void) 177 { 178 return (TAILQ_FIRST(&providers)); 179 } 180 181 provider_p 182 provider_get_next(provider_p provider) 183 { 184 return (TAILQ_NEXT(provider, provider_next)); 185 } 186 187 /* 188 * Return change state 189 */ 190 191 uint32_t 192 provider_get_change_state(void) 193 { 194 return (change_state); 195 } 196 197