xref: /freebsd/usr.sbin/bluetooth/sdpd/sd.c (revision 3bdf775801b218aa5a89564839405b122f4b233e)
1 /*
2  * sd.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: sd.c,v 1.4 2004/01/13 01:54:39 max Exp $
29  * $FreeBSD$
30  */
31 
32 #include <sys/queue.h>
33 #include <bluetooth.h>
34 #include <sdp.h>
35 #include <string.h>
36 #include "profile.h"
37 #include "provider.h"
38 
39 static int32_t
40 sd_profile_create_service_class_id_list(
41 		uint8_t *buf, uint8_t const * const eob,
42 		uint8_t const *data, uint32_t datalen)
43 {
44 	static uint16_t	service_classes[] = {
45 		SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER
46 	};
47 
48 	return (common_profile_create_service_class_id_list(
49 			buf, eob,
50 			(uint8_t const *) service_classes,
51 			sizeof(service_classes)));
52 }
53 
54 static int32_t
55 sd_profile_create_bluetooth_profile_descriptor_list(
56 		uint8_t *buf, uint8_t const * const eob,
57 		uint8_t const *data, uint32_t datalen)
58 {
59 	static uint16_t profile_descriptor_list[] = {
60 		SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER,
61 		0x0100
62 	};
63 
64 	return (common_profile_create_bluetooth_profile_descriptor_list(
65 			buf, eob,
66 			(uint8_t const *) profile_descriptor_list,
67 			sizeof(profile_descriptor_list)));
68 }
69 
70 static int32_t
71 sd_profile_create_service_id(
72 		uint8_t *buf, uint8_t const * const eob,
73 		uint8_t const *data, uint32_t datalen)
74 {
75 	if (buf + 3 > eob)
76 		return (-1);
77 
78 	/*
79 	 * The ServiceID is a UUID that universally and uniquely identifies
80 	 * the service instance described by the service record. This service
81 	 * attribute is particularly useful if the same service is described
82 	 * by service records in more than one SDP server
83 	 */
84 
85 	SDP_PUT8(SDP_DATA_UUID16, buf);
86 	SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf); /* XXX ??? */
87 
88 	return (3);
89 }
90 
91 static int32_t
92 sd_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[] = "Bluetooth service discovery";
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 sd_profile_create_protocol_descriptor_list(
105 		uint8_t *buf, uint8_t const * const eob,
106 		uint8_t const *data, uint32_t datalen)
107 {
108 	if (buf + 12 > eob)
109 		return (-1);
110 
111 	SDP_PUT8(SDP_DATA_SEQ8, buf);
112 	SDP_PUT8(10, buf);
113 
114 	SDP_PUT8(SDP_DATA_SEQ8, buf);
115 	SDP_PUT8(3, buf);
116 	SDP_PUT8(SDP_DATA_UUID16, buf);
117 	SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
118 
119 	SDP_PUT8(SDP_DATA_SEQ8, buf);
120 	SDP_PUT8(3, buf);
121 	SDP_PUT8(SDP_DATA_UUID16, buf);
122 	SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf);
123 
124 	return (12);
125 }
126 
127 static int32_t
128 sd_profile_create_browse_group_list(
129 		uint8_t *buf, uint8_t const * const eob,
130 		uint8_t const *data, uint32_t datalen)
131 {
132 	if (buf + 5 > eob)
133 		return (-1);
134 
135 	SDP_PUT8(SDP_DATA_SEQ8, buf);
136 	SDP_PUT8(3, buf);
137 
138 	/*
139 	 * The top-level browse group ID, called PublicBrowseRoot and
140 	 * representing the root of the browsing hierarchy, has the value
141 	 * 00001002-0000-1000-8000-00805F9B34FB (UUID16: 0x1002) from the
142 	 * Bluetooth Assigned Numbers document
143 	 */
144 
145 	SDP_PUT8(SDP_DATA_UUID16, buf);
146 	SDP_PUT16(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, buf);
147 
148 	return (5);
149 }
150 
151 static int32_t
152 sd_profile_create_version_number_list(
153 		uint8_t *buf, uint8_t const * const eob,
154 		uint8_t const *data, uint32_t datalen)
155 {
156 	if (buf + 5 > eob)
157 		return (-1);
158 
159 	SDP_PUT8(SDP_DATA_SEQ8, buf);
160 	SDP_PUT8(3, buf);
161 
162 	/*
163 	 * The VersionNumberList is a data element sequence in which each
164 	 * element of the sequence is a version number supported by the SDP
165 	 * server. A version number is a 16-bit unsigned integer consisting
166 	 * of two fields. The higher-order 8 bits contain the major version
167 	 * number field and the low-order 8 bits contain the minor version
168 	 * number field. The initial version of SDP has a major version of
169 	 * 1 and a minor version of 0
170 	 */
171 
172 	SDP_PUT8(SDP_DATA_UINT16, buf);
173 	SDP_PUT16(0x0100, buf);
174 
175 	return (5);
176 }
177 
178 static int32_t
179 sd_profile_create_service_database_state(
180 		uint8_t *buf, uint8_t const * const eob,
181 		uint8_t const *data, uint32_t datalen)
182 {
183 	uint32_t	change_state = provider_get_change_state();
184 
185 	if (buf + 5 > eob)
186 		return (-1);
187 
188 	SDP_PUT8(SDP_DATA_UINT32, buf);
189 	SDP_PUT32(change_state, buf);
190 
191 	return (5);
192 }
193 
194 static attr_t	sd_profile_attrs[] = {
195 	{ SDP_ATTR_SERVICE_RECORD_HANDLE,
196 	  common_profile_create_service_record_handle },
197 	{ SDP_ATTR_SERVICE_CLASS_ID_LIST,
198 	  sd_profile_create_service_class_id_list },
199 	{ SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
200 	  sd_profile_create_bluetooth_profile_descriptor_list },
201 	{ SDP_ATTR_SERVICE_ID,
202 	  sd_profile_create_service_id },
203 	{ SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST,
204 	  common_profile_create_language_base_attribute_id_list },
205 	{ SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET,
206 	  sd_profile_create_service_name },
207 	{ SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET,
208 	  sd_profile_create_service_name },
209 	{ SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_PROVIDER_NAME_OFFSET,
210 	  common_profile_create_service_provider_name },
211 	{ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
212 	  sd_profile_create_protocol_descriptor_list },
213 	{ SDP_ATTR_BROWSE_GROUP_LIST,
214 	  sd_profile_create_browse_group_list },
215 	{ SDP_ATTR_VERSION_NUMBER_LIST,
216 	  sd_profile_create_version_number_list },
217 	{ SDP_ATTR_SERVICE_DATABASE_STATE,
218 	  sd_profile_create_service_database_state },
219 	{ 0, NULL } /* end entry */
220 };
221 
222 profile_t	sd_profile_descriptor = {
223 	SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER,
224 	0,
225 	(profile_data_valid_p) NULL,
226 	(attr_t const * const) &sd_profile_attrs
227 };
228 
229