1124758Semax/*
2124758Semax * provider.c
3124758Semax *
4124758Semax * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5124758Semax * All rights reserved.
6124758Semax *
7124758Semax * Redistribution and use in source and binary forms, with or without
8124758Semax * modification, are permitted provided that the following conditions
9124758Semax * are met:
10124758Semax * 1. Redistributions of source code must retain the above copyright
11124758Semax *    notice, this list of conditions and the following disclaimer.
12124758Semax * 2. Redistributions in binary form must reproduce the above copyright
13124758Semax *    notice, this list of conditions and the following disclaimer in the
14124758Semax *    documentation and/or other materials provided with the distribution.
15124758Semax *
16124758Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17124758Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18124758Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19124758Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20124758Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21124758Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22124758Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23124758Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24124758Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25124758Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26124758Semax * SUCH DAMAGE.
27124758Semax *
28124758Semax * $Id: provider.c,v 1.5 2004/01/13 01:54:39 max Exp $
29124758Semax * $FreeBSD$
30124758Semax */
31124758Semax
32124758Semax#include <sys/queue.h>
33124758Semax#include <bluetooth.h>
34124758Semax#include <string.h>
35124758Semax#include <stdlib.h>
36124758Semax#include "profile.h"
37124758Semax#include "provider.h"
38124758Semax
39124758Semaxstatic TAILQ_HEAD(, provider)	providers = TAILQ_HEAD_INITIALIZER(providers);
40124758Semaxstatic uint32_t			change_state = 0;
41124758Semaxstatic uint32_t			handle = 0;
42124758Semax
43124758Semax/*
44124758Semax * Register Service Discovery provider.
45124758Semax * Should not be called more the once.
46124758Semax */
47124758Semax
48124758Semaxint32_t
49124758Semaxprovider_register_sd(int32_t fd)
50124758Semax{
51124758Semax	extern profile_t	sd_profile_descriptor;
52124758Semax	extern profile_t	bgd_profile_descriptor;
53124758Semax
54124758Semax	provider_p		sd = calloc(1, sizeof(*sd));
55124758Semax	provider_p		bgd = calloc(1, sizeof(*bgd));
56124758Semax
57124758Semax	if (sd == NULL || bgd == NULL) {
58124758Semax		if (sd != NULL)
59124758Semax			free(sd);
60124758Semax
61124758Semax		if (bgd != NULL)
62124758Semax			free(bgd);
63124758Semax
64124758Semax		return (-1);
65124758Semax	}
66124758Semax
67124758Semax	sd->profile = &sd_profile_descriptor;
68124758Semax	bgd->handle = 0;
69124758Semax	sd->fd = fd;
70124758Semax	TAILQ_INSERT_HEAD(&providers, sd, provider_next);
71124758Semax
72124758Semax	bgd->profile = &bgd_profile_descriptor;
73124758Semax	bgd->handle = 1;
74124758Semax	sd->fd = fd;
75124758Semax	TAILQ_INSERT_AFTER(&providers, sd, bgd, provider_next);
76124758Semax
77124758Semax	change_state ++;
78124758Semax
79124758Semax	return (0);
80124758Semax}
81124758Semax
82124758Semax/*
83124758Semax * Register new provider for a given profile, bdaddr and session.
84124758Semax */
85124758Semax
86124758Semaxprovider_p
87124758Semaxprovider_register(profile_p const profile, bdaddr_p const bdaddr, int32_t fd,
88124758Semax	uint8_t const *data, uint32_t datalen)
89124758Semax{
90124758Semax	provider_p	provider = calloc(1, sizeof(*provider));
91124758Semax
92124758Semax	if (provider != NULL) {
93124758Semax		provider->data = malloc(datalen);
94124758Semax		if (provider->data != NULL) {
95124758Semax			provider->profile = profile;
96124758Semax			memcpy(provider->data, data, datalen);
97124758Semax
98124758Semax			/*
99124758Semax			 * Record handles 0x0 and 0x1 are reserved
100124758Semax			 * for SDP itself
101124758Semax			 */
102124758Semax
103124758Semax			if (++ handle <= 1)
104124758Semax				handle = 2;
105124758Semax
106124758Semax			provider->handle = handle;
107124758Semax
108124758Semax			memcpy(&provider->bdaddr, bdaddr,
109124758Semax				sizeof(provider->bdaddr));
110124758Semax			provider->fd = fd;
111124758Semax
112124758Semax			TAILQ_INSERT_TAIL(&providers, provider, provider_next);
113124758Semax			change_state ++;
114124758Semax		} else {
115124758Semax			free(provider);
116124758Semax			provider = NULL;
117124758Semax		}
118124758Semax	}
119124758Semax
120124758Semax	return (provider);
121124758Semax}
122124758Semax
123124758Semax/*
124124758Semax * Unregister provider
125124758Semax */
126124758Semax
127124758Semaxvoid
128124758Semaxprovider_unregister(provider_p provider)
129124758Semax{
130124758Semax	TAILQ_REMOVE(&providers, provider, provider_next);
131124758Semax	if (provider->data != NULL)
132124758Semax		free(provider->data);
133124758Semax	free(provider);
134124758Semax	change_state ++;
135124758Semax}
136124758Semax
137124758Semax/*
138124758Semax * Update provider data
139124758Semax */
140124758Semax
141124758Semaxint32_t
142124758Semaxprovider_update(provider_p provider, uint8_t const *data, uint32_t datalen)
143124758Semax{
144124758Semax	uint8_t	*new_data = (uint8_t *) realloc(provider->data, datalen);
145124758Semax
146124758Semax	if (new_data == NULL)
147124758Semax		return (-1);
148124758Semax
149124758Semax	memcpy(new_data, data, datalen);
150124758Semax	provider->data = new_data;
151124758Semax
152124758Semax	return (0);
153124758Semax}
154124758Semax
155124758Semax/*
156124758Semax * Get a provider for given record handle
157124758Semax */
158124758Semax
159124758Semaxprovider_p
160124758Semaxprovider_by_handle(uint32_t handle)
161124758Semax{
162124758Semax	provider_p	provider = NULL;
163124758Semax
164124758Semax	TAILQ_FOREACH(provider, &providers, provider_next)
165124758Semax		if (provider->handle == handle)
166124758Semax			break;
167124758Semax
168124758Semax	return (provider);
169124758Semax}
170124758Semax
171124758Semax/*
172124758Semax * Cursor access
173124758Semax */
174124758Semax
175124758Semaxprovider_p
176124758Semaxprovider_get_first(void)
177124758Semax{
178124758Semax	return (TAILQ_FIRST(&providers));
179124758Semax}
180124758Semax
181124758Semaxprovider_p
182124758Semaxprovider_get_next(provider_p provider)
183124758Semax{
184124758Semax	return (TAILQ_NEXT(provider, provider_next));
185124758Semax}
186124758Semax
187124758Semax/*
188124758Semax * Return change state
189124758Semax */
190124758Semax
191124758Semaxuint32_t
192124758Semaxprovider_get_change_state(void)
193124758Semax{
194124758Semax	return (change_state);
195124758Semax}
196124758Semax
197