11de7b4b8SPedro F. Giffuni /*-
207be7a6cSMaksim Yevmenkin * provider.c
307be7a6cSMaksim Yevmenkin *
4*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni *
607be7a6cSMaksim Yevmenkin * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
707be7a6cSMaksim Yevmenkin * All rights reserved.
807be7a6cSMaksim Yevmenkin *
907be7a6cSMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without
1007be7a6cSMaksim Yevmenkin * modification, are permitted provided that the following conditions
1107be7a6cSMaksim Yevmenkin * are met:
1207be7a6cSMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright
1307be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer.
1407be7a6cSMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright
1507be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the
1607be7a6cSMaksim Yevmenkin * documentation and/or other materials provided with the distribution.
1707be7a6cSMaksim Yevmenkin *
1807be7a6cSMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1907be7a6cSMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2007be7a6cSMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2107be7a6cSMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2207be7a6cSMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2307be7a6cSMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2407be7a6cSMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2507be7a6cSMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2607be7a6cSMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2707be7a6cSMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2807be7a6cSMaksim Yevmenkin * SUCH DAMAGE.
2907be7a6cSMaksim Yevmenkin *
3007be7a6cSMaksim Yevmenkin * $Id: provider.c,v 1.5 2004/01/13 01:54:39 max Exp $
3107be7a6cSMaksim Yevmenkin */
3207be7a6cSMaksim Yevmenkin
3307be7a6cSMaksim Yevmenkin #include <sys/queue.h>
348d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
3507be7a6cSMaksim Yevmenkin #include <bluetooth.h>
3607be7a6cSMaksim Yevmenkin #include <string.h>
3707be7a6cSMaksim Yevmenkin #include <stdlib.h>
3807be7a6cSMaksim Yevmenkin #include "profile.h"
3907be7a6cSMaksim Yevmenkin #include "provider.h"
4007be7a6cSMaksim Yevmenkin
4107be7a6cSMaksim Yevmenkin static TAILQ_HEAD(, provider) providers = TAILQ_HEAD_INITIALIZER(providers);
4207be7a6cSMaksim Yevmenkin static uint32_t change_state = 0;
4307be7a6cSMaksim Yevmenkin static uint32_t handle = 0;
4407be7a6cSMaksim Yevmenkin
4507be7a6cSMaksim Yevmenkin /*
4607be7a6cSMaksim Yevmenkin * Register Service Discovery provider.
4707be7a6cSMaksim Yevmenkin * Should not be called more the once.
4807be7a6cSMaksim Yevmenkin */
4907be7a6cSMaksim Yevmenkin
5007be7a6cSMaksim Yevmenkin int32_t
provider_register_sd(int32_t fd)5107be7a6cSMaksim Yevmenkin provider_register_sd(int32_t fd)
5207be7a6cSMaksim Yevmenkin {
5307be7a6cSMaksim Yevmenkin extern profile_t sd_profile_descriptor;
5407be7a6cSMaksim Yevmenkin extern profile_t bgd_profile_descriptor;
5507be7a6cSMaksim Yevmenkin
5607be7a6cSMaksim Yevmenkin provider_p sd = calloc(1, sizeof(*sd));
5707be7a6cSMaksim Yevmenkin provider_p bgd = calloc(1, sizeof(*bgd));
5807be7a6cSMaksim Yevmenkin
5907be7a6cSMaksim Yevmenkin if (sd == NULL || bgd == NULL) {
6007be7a6cSMaksim Yevmenkin if (sd != NULL)
6107be7a6cSMaksim Yevmenkin free(sd);
6207be7a6cSMaksim Yevmenkin
6307be7a6cSMaksim Yevmenkin if (bgd != NULL)
6407be7a6cSMaksim Yevmenkin free(bgd);
6507be7a6cSMaksim Yevmenkin
6607be7a6cSMaksim Yevmenkin return (-1);
6707be7a6cSMaksim Yevmenkin }
6807be7a6cSMaksim Yevmenkin
6907be7a6cSMaksim Yevmenkin sd->profile = &sd_profile_descriptor;
7007be7a6cSMaksim Yevmenkin bgd->handle = 0;
7107be7a6cSMaksim Yevmenkin sd->fd = fd;
7207be7a6cSMaksim Yevmenkin TAILQ_INSERT_HEAD(&providers, sd, provider_next);
7307be7a6cSMaksim Yevmenkin
7407be7a6cSMaksim Yevmenkin bgd->profile = &bgd_profile_descriptor;
7507be7a6cSMaksim Yevmenkin bgd->handle = 1;
7607be7a6cSMaksim Yevmenkin sd->fd = fd;
7707be7a6cSMaksim Yevmenkin TAILQ_INSERT_AFTER(&providers, sd, bgd, provider_next);
7807be7a6cSMaksim Yevmenkin
7907be7a6cSMaksim Yevmenkin change_state ++;
8007be7a6cSMaksim Yevmenkin
8107be7a6cSMaksim Yevmenkin return (0);
8207be7a6cSMaksim Yevmenkin }
8307be7a6cSMaksim Yevmenkin
8407be7a6cSMaksim Yevmenkin /*
8507be7a6cSMaksim Yevmenkin * Register new provider for a given profile, bdaddr and session.
8607be7a6cSMaksim Yevmenkin */
8707be7a6cSMaksim Yevmenkin
8807be7a6cSMaksim Yevmenkin provider_p
provider_register(profile_p const profile,bdaddr_p const bdaddr,int32_t fd,uint8_t const * data,uint32_t datalen)8907be7a6cSMaksim Yevmenkin provider_register(profile_p const profile, bdaddr_p const bdaddr, int32_t fd,
9007be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
9107be7a6cSMaksim Yevmenkin {
9207be7a6cSMaksim Yevmenkin provider_p provider = calloc(1, sizeof(*provider));
9307be7a6cSMaksim Yevmenkin
9407be7a6cSMaksim Yevmenkin if (provider != NULL) {
9507be7a6cSMaksim Yevmenkin provider->data = malloc(datalen);
9607be7a6cSMaksim Yevmenkin if (provider->data != NULL) {
9707be7a6cSMaksim Yevmenkin provider->profile = profile;
9807be7a6cSMaksim Yevmenkin memcpy(provider->data, data, datalen);
9907be7a6cSMaksim Yevmenkin
10007be7a6cSMaksim Yevmenkin /*
10107be7a6cSMaksim Yevmenkin * Record handles 0x0 and 0x1 are reserved
10207be7a6cSMaksim Yevmenkin * for SDP itself
10307be7a6cSMaksim Yevmenkin */
10407be7a6cSMaksim Yevmenkin
10507be7a6cSMaksim Yevmenkin if (++ handle <= 1)
10607be7a6cSMaksim Yevmenkin handle = 2;
10707be7a6cSMaksim Yevmenkin
10807be7a6cSMaksim Yevmenkin provider->handle = handle;
10907be7a6cSMaksim Yevmenkin
11007be7a6cSMaksim Yevmenkin memcpy(&provider->bdaddr, bdaddr,
11107be7a6cSMaksim Yevmenkin sizeof(provider->bdaddr));
11207be7a6cSMaksim Yevmenkin provider->fd = fd;
11307be7a6cSMaksim Yevmenkin
11407be7a6cSMaksim Yevmenkin TAILQ_INSERT_TAIL(&providers, provider, provider_next);
11507be7a6cSMaksim Yevmenkin change_state ++;
11607be7a6cSMaksim Yevmenkin } else {
11707be7a6cSMaksim Yevmenkin free(provider);
11807be7a6cSMaksim Yevmenkin provider = NULL;
11907be7a6cSMaksim Yevmenkin }
12007be7a6cSMaksim Yevmenkin }
12107be7a6cSMaksim Yevmenkin
12207be7a6cSMaksim Yevmenkin return (provider);
12307be7a6cSMaksim Yevmenkin }
12407be7a6cSMaksim Yevmenkin
12507be7a6cSMaksim Yevmenkin /*
12607be7a6cSMaksim Yevmenkin * Unregister provider
12707be7a6cSMaksim Yevmenkin */
12807be7a6cSMaksim Yevmenkin
12907be7a6cSMaksim Yevmenkin void
provider_unregister(provider_p provider)13007be7a6cSMaksim Yevmenkin provider_unregister(provider_p provider)
13107be7a6cSMaksim Yevmenkin {
13207be7a6cSMaksim Yevmenkin TAILQ_REMOVE(&providers, provider, provider_next);
13307be7a6cSMaksim Yevmenkin if (provider->data != NULL)
13407be7a6cSMaksim Yevmenkin free(provider->data);
13507be7a6cSMaksim Yevmenkin free(provider);
13607be7a6cSMaksim Yevmenkin change_state ++;
13707be7a6cSMaksim Yevmenkin }
13807be7a6cSMaksim Yevmenkin
13907be7a6cSMaksim Yevmenkin /*
14007be7a6cSMaksim Yevmenkin * Update provider data
14107be7a6cSMaksim Yevmenkin */
14207be7a6cSMaksim Yevmenkin
14307be7a6cSMaksim Yevmenkin int32_t
provider_update(provider_p provider,uint8_t const * data,uint32_t datalen)14407be7a6cSMaksim Yevmenkin provider_update(provider_p provider, uint8_t const *data, uint32_t datalen)
14507be7a6cSMaksim Yevmenkin {
14607be7a6cSMaksim Yevmenkin uint8_t *new_data = (uint8_t *) realloc(provider->data, datalen);
14707be7a6cSMaksim Yevmenkin
14807be7a6cSMaksim Yevmenkin if (new_data == NULL)
14907be7a6cSMaksim Yevmenkin return (-1);
15007be7a6cSMaksim Yevmenkin
15107be7a6cSMaksim Yevmenkin memcpy(new_data, data, datalen);
15207be7a6cSMaksim Yevmenkin provider->data = new_data;
15307be7a6cSMaksim Yevmenkin
15407be7a6cSMaksim Yevmenkin return (0);
15507be7a6cSMaksim Yevmenkin }
15607be7a6cSMaksim Yevmenkin
15707be7a6cSMaksim Yevmenkin /*
15807be7a6cSMaksim Yevmenkin * Get a provider for given record handle
15907be7a6cSMaksim Yevmenkin */
16007be7a6cSMaksim Yevmenkin
16107be7a6cSMaksim Yevmenkin provider_p
provider_by_handle(uint32_t handle)16207be7a6cSMaksim Yevmenkin provider_by_handle(uint32_t handle)
16307be7a6cSMaksim Yevmenkin {
16407be7a6cSMaksim Yevmenkin provider_p provider = NULL;
16507be7a6cSMaksim Yevmenkin
16607be7a6cSMaksim Yevmenkin TAILQ_FOREACH(provider, &providers, provider_next)
16707be7a6cSMaksim Yevmenkin if (provider->handle == handle)
16807be7a6cSMaksim Yevmenkin break;
16907be7a6cSMaksim Yevmenkin
17007be7a6cSMaksim Yevmenkin return (provider);
17107be7a6cSMaksim Yevmenkin }
17207be7a6cSMaksim Yevmenkin
17307be7a6cSMaksim Yevmenkin /*
17407be7a6cSMaksim Yevmenkin * Cursor access
17507be7a6cSMaksim Yevmenkin */
17607be7a6cSMaksim Yevmenkin
17707be7a6cSMaksim Yevmenkin provider_p
provider_get_first(void)17807be7a6cSMaksim Yevmenkin provider_get_first(void)
17907be7a6cSMaksim Yevmenkin {
18007be7a6cSMaksim Yevmenkin return (TAILQ_FIRST(&providers));
18107be7a6cSMaksim Yevmenkin }
18207be7a6cSMaksim Yevmenkin
18307be7a6cSMaksim Yevmenkin provider_p
provider_get_next(provider_p provider)18407be7a6cSMaksim Yevmenkin provider_get_next(provider_p provider)
18507be7a6cSMaksim Yevmenkin {
18607be7a6cSMaksim Yevmenkin return (TAILQ_NEXT(provider, provider_next));
18707be7a6cSMaksim Yevmenkin }
18807be7a6cSMaksim Yevmenkin
18907be7a6cSMaksim Yevmenkin /*
19007be7a6cSMaksim Yevmenkin * Return change state
19107be7a6cSMaksim Yevmenkin */
19207be7a6cSMaksim Yevmenkin
19307be7a6cSMaksim Yevmenkin uint32_t
provider_get_change_state(void)19407be7a6cSMaksim Yevmenkin provider_get_change_state(void)
19507be7a6cSMaksim Yevmenkin {
19607be7a6cSMaksim Yevmenkin return (change_state);
19707be7a6cSMaksim Yevmenkin }
19807be7a6cSMaksim Yevmenkin
199