]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bluetooth/sdpd/profile.c
This commit was generated by cvs2svn to compensate for changes in r156678,
[FreeBSD/FreeBSD.git] / usr.sbin / bluetooth / sdpd / profile.c
1 /*
2  * profile.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: profile.c,v 1.6 2004/01/13 19:31:54 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 /*
40  * Lookup profile descriptor
41  */
42
43 profile_p
44 profile_get_descriptor(uint16_t uuid)
45 {
46         extern  profile_t       dun_profile_descriptor;
47         extern  profile_t       ftrn_profile_descriptor;
48         extern  profile_t       irmc_profile_descriptor;
49         extern  profile_t       irmc_command_profile_descriptor;
50         extern  profile_t       lan_profile_descriptor;
51         extern  profile_t       opush_profile_descriptor;
52         extern  profile_t       sp_profile_descriptor;
53
54         static const profile_p  profiles[] = {
55                 &dun_profile_descriptor,
56                 &ftrn_profile_descriptor,
57                 &irmc_profile_descriptor,
58                 &irmc_command_profile_descriptor,
59                 &lan_profile_descriptor,
60                 &opush_profile_descriptor,
61                 &sp_profile_descriptor
62         };
63
64         int32_t                 i;
65
66         for (i = 0; i < sizeof(profiles)/sizeof(profiles[0]); i++)
67                 if (profiles[i]->uuid == uuid)
68                         return (profiles[i]);
69
70         return (NULL);
71 }
72
73 /*
74  * Look attribute in the profile descripror
75  */
76
77 profile_attr_create_p
78 profile_get_attr(const profile_p profile, uint16_t attr)
79 {
80         attr_p  ad = (attr_p) profile->attrs;
81
82         for (; ad->create != NULL; ad ++)
83                 if (ad->attr == attr)
84                         return (ad->create);
85
86         return (NULL);
87 }
88
89 /*
90  * uint32 value32 - 5 bytes
91  */
92
93 int32_t
94 common_profile_create_service_record_handle(
95         uint8_t *buf, uint8_t const * const eob,
96         uint8_t const *data, uint32_t datalen)
97 {
98         if (buf + 5 > eob)
99                 return (-1);
100
101         SDP_PUT8(SDP_DATA_UINT32, buf);
102         SDP_PUT32(((provider_p) data)->handle, buf);
103
104         return (5);
105 }
106
107 /*
108  * seq8 len8                    - 2 bytes
109  *      uuid16 value16          - 3 bytes
110  *      [ uuid16 value ]
111  */
112
113 int32_t
114 common_profile_create_service_class_id_list(
115                 uint8_t *buf, uint8_t const * const eob,
116                 uint8_t const *data, uint32_t datalen)
117 {
118         int32_t len = 3 * (datalen >>= 1);
119
120         if (len <= 0 || len > 0xff || buf + 2 + len > eob)
121                 return (-1);
122
123         SDP_PUT8(SDP_DATA_SEQ8, buf);
124         SDP_PUT8(len, buf);
125
126         for (; datalen > 0; datalen --) {
127                 SDP_PUT8(SDP_DATA_UUID16, buf);
128                 SDP_PUT16(*((uint16_t const *)data), buf);
129                 data += sizeof(uint16_t);
130         }
131
132         return (2 + len);
133 }
134
135 /*
136  * seq8 len8                    - 2 bytes
137  *      seq 8 len8              - 2 bytes
138  *              uuid16 value16  - 3 bytes
139  *              uint16 value16  - 3 bytes
140  *      [ seq 8 len8
141  *              uuid16 value16
142  *              uint16 value16 ]
143  */
144
145 int32_t
146 common_profile_create_bluetooth_profile_descriptor_list(
147                 uint8_t *buf, uint8_t const * const eob,
148                 uint8_t const *data, uint32_t datalen)
149 {
150         int32_t len = 8 * (datalen >>= 2);
151         
152         if (len <= 0 || len > 0xff || buf + 2 + len > eob)
153                 return (-1);
154
155         SDP_PUT8(SDP_DATA_SEQ8, buf);
156         SDP_PUT8(len, buf);
157
158         for (; datalen > 0; datalen --) {
159                 SDP_PUT8(SDP_DATA_SEQ8, buf);
160                 SDP_PUT8(6, buf);
161                 SDP_PUT8(SDP_DATA_UUID16, buf);
162                 SDP_PUT16(*((uint16_t const *)data), buf);
163                 data += sizeof(uint16_t);
164                 SDP_PUT8(SDP_DATA_UINT16, buf);
165                 SDP_PUT16(*((uint16_t const *)data), buf);
166                 data += sizeof(uint16_t);
167         }
168
169         return (2 + len);
170 }
171
172 /*
173  * seq8 len8            - 2 bytes
174  *      uint16 value16  - 3 bytes
175  *      uint16 value16  - 3 bytes
176  *      uint16 value16  - 3 bytes
177  */
178
179 int32_t
180 common_profile_create_language_base_attribute_id_list(
181                 uint8_t *buf, uint8_t const * const eob,
182                 uint8_t const *data, uint32_t datalen)
183 {
184         if (buf + 11 > eob)
185                 return (-1);
186
187         SDP_PUT8(SDP_DATA_SEQ8, buf);
188         SDP_PUT8(9, buf);
189
190         /*
191          * Language code per ISO 639:1988. Use "en".
192          */
193
194         SDP_PUT8(SDP_DATA_UINT16, buf);
195         SDP_PUT16(((0x65 << 8) | 0x6e), buf);
196
197         /* 
198          * Encoding. Recommended is UTF-8. ISO639 UTF-8 MIBenum is 106 
199          * (http://www.iana.org/assignments/character-sets)
200          */
201
202         SDP_PUT8(SDP_DATA_UINT16, buf);
203         SDP_PUT16(106, buf);
204
205         /* 
206          * Offset (Primary Language Base is 0x100)
207          */
208
209         SDP_PUT8(SDP_DATA_UINT16, buf);
210         SDP_PUT16(SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID, buf);
211
212         return (11);
213 }
214
215 /*
216  * Common provider name is "FreeBSD"
217  */
218
219 int32_t
220 common_profile_create_service_provider_name(
221                 uint8_t *buf, uint8_t const * const eob,
222                 uint8_t const *data, uint32_t datalen)
223 {
224         char    provider_name[] = "FreeBSD";
225
226         return (common_profile_create_string8(buf, eob,
227                         (uint8_t const *) provider_name,
228                         strlen(provider_name)));
229 }
230
231 /*
232  * str8 len8 string
233  */
234
235 int32_t
236 common_profile_create_string8(
237                 uint8_t *buf, uint8_t const * const eob,
238                 uint8_t const *data, uint32_t datalen)
239 {
240         if (datalen == 0 || datalen > 0xff || buf + 2 + datalen > eob)
241                 return (-1);
242
243         SDP_PUT8(SDP_DATA_STR8, buf);
244         SDP_PUT8(datalen, buf);
245         memcpy(buf, data, datalen);
246
247         return (2 + datalen);
248 }
249
250 /*
251  * seq8 len8                    - 2 bytes
252  *      seq8 len8               - 2 bytes
253  *              uuid16 value16  - 3 bytes
254  *      seq8 len8               - 2 bytes
255  *              uuid16 value16  - 3 bytes
256  *              uint8 value8    - 2 bytes
257  */
258
259 int32_t
260 rfcomm_profile_create_protocol_descriptor_list(
261                 uint8_t *buf, uint8_t const * const eob,
262                 uint8_t const *data, uint32_t datalen)
263 {
264         if (datalen != 1 || buf + 14 > eob)
265                 return (-1);
266
267         SDP_PUT8(SDP_DATA_SEQ8, buf);
268         SDP_PUT8(12, buf);
269
270         SDP_PUT8(SDP_DATA_SEQ8, buf);
271         SDP_PUT8(3, buf);
272         SDP_PUT8(SDP_DATA_UUID16, buf);
273         SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
274
275         SDP_PUT8(SDP_DATA_SEQ8, buf);
276         SDP_PUT8(5, buf);
277         SDP_PUT8(SDP_DATA_UUID16, buf);
278         SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf);
279         SDP_PUT8(SDP_DATA_UINT8, buf);
280         SDP_PUT8(*data, buf);
281
282         return (14);
283 }
284
285 /*
286  * seq8 len8                    - 2 bytes
287  *      seq8 len8               - 2 bytes
288  *              uuid16 value16  - 3 bytes
289  *      seq8 len8               - 2 bytes
290  *              uuid16 value16  - 3 bytes
291  *              uint8 value8    - 2 bytes
292  *      seq8 len8               - 2 bytes
293  *              uuid16 value16  - 3 bytes
294  */
295
296 int32_t
297 obex_profile_create_protocol_descriptor_list(
298                 uint8_t *buf, uint8_t const * const eob,
299                 uint8_t const *data, uint32_t datalen)
300 {
301         if (datalen != 1 || buf + 19 > eob)
302                 return (-1);
303
304         SDP_PUT8(SDP_DATA_SEQ8, buf);
305         SDP_PUT8(17, buf);
306
307         SDP_PUT8(SDP_DATA_SEQ8, buf);
308         SDP_PUT8(3, buf);
309         SDP_PUT8(SDP_DATA_UUID16, buf);
310         SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
311
312         SDP_PUT8(SDP_DATA_SEQ8, buf);
313         SDP_PUT8(5, buf);
314         SDP_PUT8(SDP_DATA_UUID16, buf);
315         SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf);
316         SDP_PUT8(SDP_DATA_UINT8, buf);
317         SDP_PUT8(*data, buf);
318
319         SDP_PUT8(SDP_DATA_SEQ8, buf);
320         SDP_PUT8(3, buf);
321         SDP_PUT8(SDP_DATA_UUID16, buf);
322         SDP_PUT16(SDP_UUID_PROTOCOL_OBEX, buf);
323
324         return (19);
325 }
326
327 /*
328  * seq8 len8
329  *      uint8 value8    - bytes
330  *      [ uint8 value 8 ]
331  */
332
333 int32_t
334 obex_profile_create_supported_formats_list(
335                 uint8_t *buf, uint8_t const * const eob,
336                 uint8_t const *data, uint32_t datalen)
337 {
338         int32_t len = 2 * datalen;
339
340         if (len <= 0 || len > 0xff || buf + 2 + len > eob)
341                 return (-1);
342
343         SDP_PUT8(SDP_DATA_SEQ8, buf);
344         SDP_PUT8(len, buf);
345
346         for (; datalen > 0; datalen --) {
347                 SDP_PUT8(SDP_DATA_UINT8, buf);
348                 SDP_PUT8(*data++, buf);
349         }
350
351         return (2 + len);
352 }
353
354 /*
355  * verify server channel number (the first byte in the data)
356  */
357
358 int32_t
359 common_profile_server_channel_valid(uint8_t const *data, uint32_t datalen)
360 {
361         if (data[0] < 1 || data[0] > 30)
362                 return (0);
363
364         return (1);
365 }
366
367 /*
368  * verify server channel number and supported_formats_size 
369  * sdp_opush_profile and sdp_irmc_profile
370  */
371
372 int32_t
373 obex_profile_data_valid(uint8_t const *data, uint32_t datalen)
374 {
375         sdp_opush_profile_p     opush = (sdp_opush_profile_p) data;
376
377         if (opush->server_channel < 1 ||
378             opush->server_channel > 30 ||
379             opush->supported_formats_size == 0 ||
380             opush->supported_formats_size > sizeof(opush->supported_formats))
381                 return (0);
382
383         return (1);
384 }
385