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 #define L2CAP_SOCKET_CHECKED 34 #include <bluetooth.h> 35 #include <string.h> 36 #include <stdlib.h> 37 #include "profile.h" 38 #include "provider.h" 39 40 static TAILQ_HEAD(, provider) providers = TAILQ_HEAD_INITIALIZER(providers); 41 static uint32_t change_state = 0; 42 static uint32_t handle = 0; 43 44 /* 45 * Register Service Discovery provider. 46 * Should not be called more the once. 47 */ 48 49 int32_t 50 provider_register_sd(int32_t fd) 51 { 52 extern profile_t sd_profile_descriptor; 53 extern profile_t bgd_profile_descriptor; 54 55 provider_p sd = calloc(1, sizeof(*sd)); 56 provider_p bgd = calloc(1, sizeof(*bgd)); 57 58 if (sd == NULL || bgd == NULL) { 59 if (sd != NULL) 60 free(sd); 61 62 if (bgd != NULL) 63 free(bgd); 64 65 return (-1); 66 } 67 68 sd->profile = &sd_profile_descriptor; 69 bgd->handle = 0; 70 sd->fd = fd; 71 TAILQ_INSERT_HEAD(&providers, sd, provider_next); 72 73 bgd->profile = &bgd_profile_descriptor; 74 bgd->handle = 1; 75 sd->fd = fd; 76 TAILQ_INSERT_AFTER(&providers, sd, bgd, provider_next); 77 78 change_state ++; 79 80 return (0); 81 } 82 83 /* 84 * Register new provider for a given profile, bdaddr and session. 85 */ 86 87 provider_p 88 provider_register(profile_p const profile, bdaddr_p const bdaddr, int32_t fd, 89 uint8_t const *data, uint32_t datalen) 90 { 91 provider_p provider = calloc(1, sizeof(*provider)); 92 93 if (provider != NULL) { 94 provider->data = malloc(datalen); 95 if (provider->data != NULL) { 96 provider->profile = profile; 97 memcpy(provider->data, data, datalen); 98 99 /* 100 * Record handles 0x0 and 0x1 are reserved 101 * for SDP itself 102 */ 103 104 if (++ handle <= 1) 105 handle = 2; 106 107 provider->handle = handle; 108 109 memcpy(&provider->bdaddr, bdaddr, 110 sizeof(provider->bdaddr)); 111 provider->fd = fd; 112 113 TAILQ_INSERT_TAIL(&providers, provider, provider_next); 114 change_state ++; 115 } else { 116 free(provider); 117 provider = NULL; 118 } 119 } 120 121 return (provider); 122 } 123 124 /* 125 * Unregister provider 126 */ 127 128 void 129 provider_unregister(provider_p provider) 130 { 131 TAILQ_REMOVE(&providers, provider, provider_next); 132 if (provider->data != NULL) 133 free(provider->data); 134 free(provider); 135 change_state ++; 136 } 137 138 /* 139 * Update provider data 140 */ 141 142 int32_t 143 provider_update(provider_p provider, uint8_t const *data, uint32_t datalen) 144 { 145 uint8_t *new_data = (uint8_t *) realloc(provider->data, datalen); 146 147 if (new_data == NULL) 148 return (-1); 149 150 memcpy(new_data, data, datalen); 151 provider->data = new_data; 152 153 return (0); 154 } 155 156 /* 157 * Get a provider for given record handle 158 */ 159 160 provider_p 161 provider_by_handle(uint32_t handle) 162 { 163 provider_p provider = NULL; 164 165 TAILQ_FOREACH(provider, &providers, provider_next) 166 if (provider->handle == handle) 167 break; 168 169 return (provider); 170 } 171 172 /* 173 * Cursor access 174 */ 175 176 provider_p 177 provider_get_first(void) 178 { 179 return (TAILQ_FIRST(&providers)); 180 } 181 182 provider_p 183 provider_get_next(provider_p provider) 184 { 185 return (TAILQ_NEXT(provider, provider_next)); 186 } 187 188 /* 189 * Return change state 190 */ 191 192 uint32_t 193 provider_get_change_state(void) 194 { 195 return (change_state); 196 } 197 198