tizen 2.3.1 release
[framework/connectivity/bluez.git] / src / eir.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2011  Nokia Corporation
6  *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
7  *
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include <stdint.h>
33 #include <stdbool.h>
34 #include <glib.h>
35
36 #include "lib/bluetooth.h"
37 #include "lib/hci.h"
38 #include "lib/sdp.h"
39
40 #include "src/shared/util.h"
41 #include "uuid-helper.h"
42 #include "eir.h"
43
44 #define EIR_OOB_MIN (2 + 6)
45
46 void eir_data_free(struct eir_data *eir)
47 {
48         g_slist_free_full(eir->services, free);
49         eir->services = NULL;
50         g_free(eir->name);
51         eir->name = NULL;
52         g_free(eir->hash);
53         eir->hash = NULL;
54         g_free(eir->randomizer);
55         eir->randomizer = NULL;
56         g_slist_free_full(eir->msd_list, g_free);
57         eir->msd_list = NULL;
58 #ifdef __TIZEN_PATCH__
59         g_free(eir->manufacturer_data);
60         eir->manufacturer_data = NULL;
61 #endif
62 }
63
64 static void eir_parse_uuid16(struct eir_data *eir, const void *data,
65                                                                 uint8_t len)
66 {
67         const uint16_t *uuid16 = data;
68         uuid_t service;
69         char *uuid_str;
70         unsigned int i;
71
72         service.type = SDP_UUID16;
73         for (i = 0; i < len / 2; i++, uuid16++) {
74                 service.value.uuid16 = get_le16(uuid16);
75
76                 uuid_str = bt_uuid2string(&service);
77                 if (!uuid_str)
78                         continue;
79                 eir->services = g_slist_append(eir->services, uuid_str);
80         }
81 }
82
83 static void eir_parse_uuid32(struct eir_data *eir, const void *data,
84                                                                 uint8_t len)
85 {
86         const uint32_t *uuid32 = data;
87         uuid_t service;
88         char *uuid_str;
89         unsigned int i;
90
91         service.type = SDP_UUID32;
92         for (i = 0; i < len / 4; i++, uuid32++) {
93                 service.value.uuid32 = get_le32(uuid32);
94
95                 uuid_str = bt_uuid2string(&service);
96                 if (!uuid_str)
97                         continue;
98                 eir->services = g_slist_append(eir->services, uuid_str);
99         }
100 }
101
102 static void eir_parse_uuid128(struct eir_data *eir, const uint8_t *data,
103                                                                 uint8_t len)
104 {
105         const uint8_t *uuid_ptr = data;
106         uuid_t service;
107         char *uuid_str;
108         unsigned int i;
109         int k;
110
111         service.type = SDP_UUID128;
112         for (i = 0; i < len / 16; i++) {
113                 for (k = 0; k < 16; k++)
114                         service.value.uuid128.data[k] = uuid_ptr[16 - k - 1];
115                 uuid_str = bt_uuid2string(&service);
116                 if (!uuid_str)
117                         continue;
118                 eir->services = g_slist_append(eir->services, uuid_str);
119                 uuid_ptr += 16;
120         }
121 }
122
123 static char *name2utf8(const uint8_t *name, uint8_t len)
124 {
125 #ifdef __TIZEN_PATCH__
126         char *utf8_name;
127         char *in_name;
128         char *ptr;
129
130         in_name = g_malloc0(sizeof(char) * (len + 1));
131         /* Fix : NULL_RETURNS */
132         if (in_name == NULL)
133                 return NULL;
134         memcpy(in_name, name, sizeof(char) * len);
135         in_name[len] = '\0';
136
137         if (!g_utf8_validate(in_name, -1, (const char **)&ptr))
138                 *ptr = '\0';
139
140         utf8_name = g_strdup(in_name);
141         g_free(in_name);
142
143         return utf8_name;
144 #else
145         char utf8_name[HCI_MAX_NAME_LENGTH + 2];
146         int i;
147
148         if (g_utf8_validate((const char *) name, len, NULL))
149                 return g_strndup((char *) name, len);
150
151         memset(utf8_name, 0, sizeof(utf8_name));
152         strncpy(utf8_name, (char *) name, len);
153
154         /* Assume ASCII, and replace all non-ASCII with spaces */
155         for (i = 0; utf8_name[i] != '\0'; i++) {
156                 if (!isascii(utf8_name[i]))
157                         utf8_name[i] = ' ';
158         }
159
160         /* Remove leading and trailing whitespace characters */
161         g_strstrip(utf8_name);
162
163         return g_strdup(utf8_name);
164 #endif
165 }
166
167 static void eir_parse_msd(struct eir_data *eir, const uint8_t *data,
168                                                                 uint8_t len)
169 {
170         struct eir_msd *msd;
171
172         if (len < 2 || len > 2 + sizeof(msd->data))
173                 return;
174
175         msd = g_malloc(sizeof(*msd));
176         msd->company = get_le16(data);
177         msd->data_len = len - 2;
178         memcpy(&msd->data, data + 2, msd->data_len);
179
180         eir->msd_list = g_slist_append(eir->msd_list, msd);
181 }
182
183 void eir_parse(struct eir_data *eir, const uint8_t *eir_data, uint8_t eir_len)
184 {
185         uint16_t len = 0;
186
187         eir->flags = 0;
188         eir->tx_power = 127;
189
190         /* No EIR data to parse */
191         if (eir_data == NULL)
192                 return;
193
194         while (len < eir_len - 1) {
195                 uint8_t field_len = eir_data[0];
196                 const uint8_t *data;
197                 uint8_t data_len;
198
199                 /* Check for the end of EIR */
200                 if (field_len == 0)
201                         break;
202
203                 len += field_len + 1;
204
205                 /* Do not continue EIR Data parsing if got incorrect length */
206                 if (len > eir_len)
207                         break;
208
209                 data = &eir_data[2];
210                 data_len = field_len - 1;
211
212                 switch (eir_data[1]) {
213                 case EIR_UUID16_SOME:
214                 case EIR_UUID16_ALL:
215                         eir_parse_uuid16(eir, data, data_len);
216                         break;
217
218                 case EIR_UUID32_SOME:
219                 case EIR_UUID32_ALL:
220                         eir_parse_uuid32(eir, data, data_len);
221                         break;
222
223                 case EIR_UUID128_SOME:
224                 case EIR_UUID128_ALL:
225                         eir_parse_uuid128(eir, data, data_len);
226                         break;
227
228                 case EIR_FLAGS:
229                         if (data_len > 0)
230                                 eir->flags = *data;
231                         break;
232
233                 case EIR_NAME_SHORT:
234                 case EIR_NAME_COMPLETE:
235                         /* Some vendors put a NUL byte terminator into
236                          * the name */
237                         while (data_len > 0 && data[data_len - 1] == '\0')
238                                 data_len--;
239
240                         g_free(eir->name);
241
242                         eir->name = name2utf8(data, data_len);
243                         eir->name_complete = eir_data[1] == EIR_NAME_COMPLETE;
244                         break;
245
246                 case EIR_TX_POWER:
247                         if (data_len < 1)
248                                 break;
249                         eir->tx_power = (int8_t) data[0];
250                         break;
251
252                 case EIR_CLASS_OF_DEV:
253                         if (data_len < 3)
254                                 break;
255                         eir->class = data[0] | (data[1] << 8) |
256                                                         (data[2] << 16);
257                         break;
258
259                 case EIR_GAP_APPEARANCE:
260                         if (data_len < 2)
261                                 break;
262                         eir->appearance = get_le16(data);
263                         break;
264
265                 case EIR_SSP_HASH:
266                         if (data_len < 16)
267                                 break;
268                         eir->hash = g_memdup(data, 16);
269                         break;
270
271                 case EIR_SSP_RANDOMIZER:
272                         if (data_len < 16)
273                                 break;
274                         eir->randomizer = g_memdup(data, 16);
275                         break;
276
277                 case EIR_DEVICE_ID:
278                         if (data_len < 8)
279                                 break;
280
281                         eir->did_source = data[0] | (data[1] << 8);
282                         eir->did_vendor = data[2] | (data[3] << 8);
283                         eir->did_product = data[4] | (data[5] << 8);
284                         eir->did_version = data[6] | (data[7] << 8);
285                         break;
286
287                 case EIR_MANUFACTURER_DATA:
288 #ifdef __TIZEN_PATCH__
289                         if (data_len < 1)
290                                 break;
291
292                         eir->manufacturer_data = g_memdup(data,
293                                                                 data_len);
294                         eir->manufacturer_data_len = data_len;
295 #endif
296                         eir_parse_msd(eir, data, data_len);
297
298                         break;
299                 }
300
301                 eir_data += field_len + 1;
302         }
303 }
304
305 int eir_parse_oob(struct eir_data *eir, uint8_t *eir_data, uint16_t eir_len)
306 {
307
308         if (eir_len < EIR_OOB_MIN)
309                 return -1;
310
311         if (eir_len != get_le16(eir_data))
312                 return -1;
313
314         eir_data += sizeof(uint16_t);
315         eir_len -= sizeof(uint16_t);
316
317         memcpy(&eir->addr, eir_data, sizeof(bdaddr_t));
318         eir_data += sizeof(bdaddr_t);
319         eir_len -= sizeof(bdaddr_t);
320
321         /* optional OOB EIR data */
322         if (eir_len > 0)
323                 eir_parse(eir, eir_data, eir_len);
324
325         return 0;
326 }
327
328 #define SIZEOF_UUID128 16
329
330 static void eir_generate_uuid128(sdp_list_t *list, uint8_t *ptr,
331                                                         uint16_t *eir_len)
332 {
333         int i, k, uuid_count = 0;
334         uint16_t len = *eir_len;
335         uint8_t *uuid128;
336         bool truncated = false;
337
338         /* Store UUIDs in place, skip 2 bytes to write type and length later */
339         uuid128 = ptr + 2;
340
341         for (; list; list = list->next) {
342                 sdp_record_t *rec = list->data;
343                 uuid_t *uuid = &rec->svclass;
344                 uint8_t *uuid128_data = uuid->value.uuid128.data;
345
346                 if (uuid->type != SDP_UUID128)
347                         continue;
348
349                 /* Stop if not enough space to put next UUID128 */
350                 if ((len + 2 + SIZEOF_UUID128) > HCI_MAX_EIR_LENGTH) {
351                         truncated = true;
352                         break;
353                 }
354
355                 /* Check for duplicates, EIR data is Little Endian */
356                 for (i = 0; i < uuid_count; i++) {
357                         for (k = 0; k < SIZEOF_UUID128; k++) {
358                                 if (uuid128[i * SIZEOF_UUID128 + k] !=
359                                         uuid128_data[SIZEOF_UUID128 - 1 - k])
360                                         break;
361                         }
362                         if (k == SIZEOF_UUID128)
363                                 break;
364                 }
365
366                 if (i < uuid_count)
367                         continue;
368
369                 /* EIR data is Little Endian */
370                 for (k = 0; k < SIZEOF_UUID128; k++)
371                         uuid128[uuid_count * SIZEOF_UUID128 + k] =
372                                 uuid128_data[SIZEOF_UUID128 - 1 - k];
373
374                 len += SIZEOF_UUID128;
375                 uuid_count++;
376         }
377
378         if (uuid_count > 0 || truncated) {
379                 /* EIR Data length */
380                 ptr[0] = (uuid_count * SIZEOF_UUID128) + 1;
381                 /* EIR Data type */
382                 ptr[1] = truncated ? EIR_UUID128_SOME : EIR_UUID128_ALL;
383                 len += 2;
384                 *eir_len = len;
385         }
386 }
387
388 int eir_create_oob(const bdaddr_t *addr, const char *name, uint32_t cod,
389                         const uint8_t *hash, const uint8_t *randomizer,
390                         uint16_t did_vendor, uint16_t did_product,
391                         uint16_t did_version, uint16_t did_source,
392                         sdp_list_t *uuids, uint8_t *data)
393 {
394         sdp_list_t *l;
395         uint8_t *ptr = data;
396         uint16_t eir_optional_len = 0;
397         uint16_t eir_total_len;
398         uint16_t uuid16[HCI_MAX_EIR_LENGTH / 2];
399         int i, uuid_count = 0;
400         bool truncated = false;
401         size_t name_len;
402
403         eir_total_len =  sizeof(uint16_t) + sizeof(bdaddr_t);
404         ptr += sizeof(uint16_t);
405
406         memcpy(ptr, addr, sizeof(bdaddr_t));
407         ptr += sizeof(bdaddr_t);
408
409         if (cod > 0) {
410                 uint8_t class[3];
411
412                 class[0] = (uint8_t) cod;
413                 class[1] = (uint8_t) (cod >> 8);
414                 class[2] = (uint8_t) (cod >> 16);
415
416                 *ptr++ = 4;
417                 *ptr++ = EIR_CLASS_OF_DEV;
418
419                 memcpy(ptr, class, sizeof(class));
420                 ptr += sizeof(class);
421
422                 eir_optional_len += sizeof(class) + 2;
423         }
424
425         if (hash) {
426                 *ptr++ = 17;
427                 *ptr++ = EIR_SSP_HASH;
428
429                 memcpy(ptr, hash, 16);
430                 ptr += 16;
431
432                 eir_optional_len += 16 + 2;
433         }
434
435         if (randomizer) {
436                 *ptr++ = 17;
437                 *ptr++ = EIR_SSP_RANDOMIZER;
438
439                 memcpy(ptr, randomizer, 16);
440                 ptr += 16;
441
442                 eir_optional_len += 16 + 2;
443         }
444
445         name_len = strlen(name);
446
447         if (name_len > 0) {
448                 /* EIR Data type */
449                 if (name_len > 48) {
450                         name_len = 48;
451                         ptr[1] = EIR_NAME_SHORT;
452                 } else
453                         ptr[1] = EIR_NAME_COMPLETE;
454
455                 /* EIR Data length */
456                 ptr[0] = name_len + 1;
457
458                 memcpy(ptr + 2, name, name_len);
459
460                 eir_optional_len += (name_len + 2);
461                 ptr += (name_len + 2);
462         }
463
464         if (did_vendor != 0x0000) {
465                 *ptr++ = 9;
466                 *ptr++ = EIR_DEVICE_ID;
467                 *ptr++ = (did_source & 0x00ff);
468                 *ptr++ = (did_source & 0xff00) >> 8;
469                 *ptr++ = (did_vendor & 0x00ff);
470                 *ptr++ = (did_vendor & 0xff00) >> 8;
471                 *ptr++ = (did_product & 0x00ff);
472                 *ptr++ = (did_product & 0xff00) >> 8;
473                 *ptr++ = (did_version & 0x00ff);
474                 *ptr++ = (did_version & 0xff00) >> 8;
475                 eir_optional_len += 10;
476         }
477
478         /* Group all UUID16 types */
479         for (l = uuids; l != NULL; l = l->next) {
480                 sdp_record_t *rec = l->data;
481                 uuid_t *uuid = &rec->svclass;
482
483                 if (uuid->type != SDP_UUID16)
484                         continue;
485
486                 if (uuid->value.uuid16 < 0x1100)
487                         continue;
488
489                 if (uuid->value.uuid16 == PNP_INFO_SVCLASS_ID)
490                         continue;
491
492                 /* Stop if not enough space to put next UUID16 */
493                 if ((eir_optional_len + 2 + sizeof(uint16_t)) >
494                                 HCI_MAX_EIR_LENGTH) {
495                         truncated = true;
496                         break;
497                 }
498
499                 /* Check for duplicates */
500                 for (i = 0; i < uuid_count; i++)
501                         if (uuid16[i] == uuid->value.uuid16)
502                                 break;
503
504                 if (i < uuid_count)
505                         continue;
506
507                 uuid16[uuid_count++] = uuid->value.uuid16;
508                 eir_optional_len += sizeof(uint16_t);
509         }
510
511         if (uuid_count > 0) {
512                 /* EIR Data length */
513                 ptr[0] = (uuid_count * sizeof(uint16_t)) + 1;
514                 /* EIR Data type */
515                 ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
516
517                 ptr += 2;
518                 eir_optional_len += 2;
519
520                 for (i = 0; i < uuid_count; i++) {
521                         *ptr++ = (uuid16[i] & 0x00ff);
522                         *ptr++ = (uuid16[i] & 0xff00) >> 8;
523                 }
524         }
525
526         /* Group all UUID128 types */
527         if (eir_optional_len <= HCI_MAX_EIR_LENGTH - 2)
528                 eir_generate_uuid128(uuids, ptr, &eir_optional_len);
529
530         eir_total_len += eir_optional_len;
531
532         /* store total length */
533         put_le16(eir_total_len, data);
534
535         return eir_total_len;
536 }