Fix build break for rpm
[framework/connectivity/bluez.git] / src / glib-helper.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <errno.h>
30
31 #include <bluetooth/bluetooth.h>
32 #include <bluetooth/sdp.h>
33 #include <bluetooth/sdp_lib.h>
34
35 #include <glib.h>
36
37 #include "btio.h"
38 #include "glib-helper.h"
39
40 char *bt_uuid2string(uuid_t *uuid)
41 {
42         gchar *str;
43         uuid_t uuid128;
44         unsigned int data0;
45         unsigned short data1;
46         unsigned short data2;
47         unsigned short data3;
48         unsigned int data4;
49         unsigned short data5;
50
51         if (!uuid)
52                 return NULL;
53
54         switch (uuid->type) {
55         case SDP_UUID16:
56                 sdp_uuid16_to_uuid128(&uuid128, uuid);
57                 break;
58         case SDP_UUID32:
59                 sdp_uuid32_to_uuid128(&uuid128, uuid);
60                 break;
61         case SDP_UUID128:
62                 memcpy(&uuid128, uuid, sizeof(uuid_t));
63                 break;
64         default:
65                 /* Type of UUID unknown */
66                 return NULL;
67         }
68
69         memcpy(&data0, &uuid128.value.uuid128.data[0], 4);
70         memcpy(&data1, &uuid128.value.uuid128.data[4], 2);
71         memcpy(&data2, &uuid128.value.uuid128.data[6], 2);
72         memcpy(&data3, &uuid128.value.uuid128.data[8], 2);
73         memcpy(&data4, &uuid128.value.uuid128.data[10], 4);
74         memcpy(&data5, &uuid128.value.uuid128.data[14], 2);
75
76         str = g_try_malloc0(MAX_LEN_UUID_STR);
77         if (!str)
78                 return NULL;
79
80         sprintf(str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
81                         g_ntohl(data0), g_ntohs(data1),
82                         g_ntohs(data2), g_ntohs(data3),
83                         g_ntohl(data4), g_ntohs(data5));
84
85         return str;
86 }
87
88 static struct {
89         const char      *name;
90         uint16_t        class;
91 } bt_services[] = {
92         { "vcp",        VIDEO_CONF_SVCLASS_ID           },
93         { "pbap",       PBAP_SVCLASS_ID                 },
94         { "sap",        SAP_SVCLASS_ID                  },
95         { "ftp",        OBEX_FILETRANS_SVCLASS_ID       },
96         { "bpp",        BASIC_PRINTING_SVCLASS_ID       },
97         { "bip",        IMAGING_SVCLASS_ID              },
98         { "synch",      IRMC_SYNC_SVCLASS_ID            },
99         { "dun",        DIALUP_NET_SVCLASS_ID           },
100         { "opp",        OBEX_OBJPUSH_SVCLASS_ID         },
101         { "fax",        FAX_SVCLASS_ID                  },
102         { "spp",        SERIAL_PORT_SVCLASS_ID          },
103         { "hsp",        HEADSET_SVCLASS_ID              },
104         { "hfp",        HANDSFREE_SVCLASS_ID            },
105         { }
106 };
107
108 static uint16_t name2class(const char *pattern)
109 {
110         int i;
111
112         for (i = 0; bt_services[i].name; i++) {
113                 if (strcasecmp(bt_services[i].name, pattern) == 0)
114                         return bt_services[i].class;
115         }
116
117         return 0;
118 }
119
120 static inline gboolean is_uuid128(const char *string)
121 {
122         return (strlen(string) == 36 &&
123                         string[8] == '-' &&
124                         string[13] == '-' &&
125                         string[18] == '-' &&
126                         string[23] == '-');
127 }
128
129 static int string2uuid16(uuid_t *uuid, const char *string)
130 {
131         int length = strlen(string);
132         char *endptr = NULL;
133         uint16_t u16;
134
135         if (length != 4 && length != 6)
136                 return -EINVAL;
137
138         u16 = strtol(string, &endptr, 16);
139         if (endptr && *endptr == '\0') {
140                 sdp_uuid16_create(uuid, u16);
141                 return 0;
142         }
143
144         return -EINVAL;
145 }
146
147 char *bt_name2string(const char *pattern)
148 {
149         uuid_t uuid;
150         uint16_t uuid16;
151         int i;
152
153         /* UUID 128 string format */
154         if (is_uuid128(pattern))
155                 return g_strdup(pattern);
156
157         /* Friendly service name format */
158         uuid16 = name2class(pattern);
159         if (uuid16)
160                 goto proceed;
161
162         /* HEX format */
163         uuid16 = strtol(pattern, NULL, 16);
164         for (i = 0; bt_services[i].class; i++) {
165                 if (bt_services[i].class == uuid16)
166                         goto proceed;
167         }
168
169         return NULL;
170
171 proceed:
172         sdp_uuid16_create(&uuid, uuid16);
173
174         return bt_uuid2string(&uuid);
175 }
176
177 int bt_string2uuid(uuid_t *uuid, const char *string)
178 {
179         uint32_t data0, data4;
180         uint16_t data1, data2, data3, data5;
181
182         if (is_uuid128(string) &&
183                         sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
184                                 &data0, &data1, &data2, &data3, &data4, &data5) == 6) {
185                 uint8_t val[16];
186
187                 data0 = g_htonl(data0);
188                 data1 = g_htons(data1);
189                 data2 = g_htons(data2);
190                 data3 = g_htons(data3);
191                 data4 = g_htonl(data4);
192                 data5 = g_htons(data5);
193
194                 memcpy(&val[0], &data0, 4);
195                 memcpy(&val[4], &data1, 2);
196                 memcpy(&val[6], &data2, 2);
197                 memcpy(&val[8], &data3, 2);
198                 memcpy(&val[10], &data4, 4);
199                 memcpy(&val[14], &data5, 2);
200
201                 sdp_uuid128_create(uuid, val);
202
203                 return 0;
204         } else {
205                 uint16_t class = name2class(string);
206                 if (class) {
207                         sdp_uuid16_create(uuid, class);
208                         return 0;
209                 }
210
211                 return string2uuid16(uuid, string);
212         }
213 }
214
215 gchar *bt_list2string(GSList *list)
216 {
217         GSList *l;
218         gchar *str, *tmp;
219
220         if (!list)
221                 return NULL;
222
223         str = g_strdup((const gchar *) list->data);
224
225         for (l = list->next; l; l = l->next) {
226                 tmp = g_strconcat(str, " " , (const gchar *) l->data, NULL);
227                 g_free(str);
228                 str = tmp;
229         }
230
231         return str;
232 }
233
234 GSList *bt_string2list(const gchar *str)
235 {
236         GSList *l = NULL;
237         gchar **uuids;
238         int i = 0;
239
240         if (!str)
241                 return NULL;
242
243         /* FIXME: eglib doesn't support g_strsplit */
244         uuids = g_strsplit(str, " ", 0);
245         if (!uuids)
246                 return NULL;
247
248         while (uuids[i]) {
249                 l = g_slist_append(l, uuids[i]);
250                 i++;
251         }
252
253         g_free(uuids);
254
255         return l;
256 }