Fix Pairing when headset have PIN other than 0000
[platform/core/connectivity/bluetooth-frwk.git] / bt-service-adaptation / services / bt-service-agent-util.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <malloc.h>
26 #include <stacktrim.h>
27
28 #include "bt-internal-types.h"
29 #include "bt-service-common.h"
30
31 gboolean _bt_agent_is_hid_keyboard(unsigned int dev_class)
32 {
33         switch ((dev_class & 0x1f00) >> 8) {
34         case 0x05:
35                 switch ((dev_class & 0xc0) >> 6) {
36                 case 0x01:
37                         /* input-keyboard" */
38                         return TRUE;
39                 default:
40                         break;
41                 }
42                 break;
43         default:
44                 break;
45         }
46
47         return FALSE;
48 }
49
50 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
51                 const char *address)
52 {
53         char *pch;
54         char *last;
55
56         pch = strtok_r(buffer, "= ,", &last);
57
58         if (pch == NULL)
59                 return FALSE;
60
61         while ((pch = strtok_r(NULL, ",", &last))) {
62                 if (0 == g_strcmp0(pch, address)) {
63                         BT_DBG("Match found\n");
64                         return TRUE;
65                 }
66         }
67         return FALSE;
68 }
69
70 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
71                 const char *partial_name)
72 {
73         char *pch;
74         char *last;
75
76         pch = strtok_r(buffer, "= ,", &last);
77
78         if (pch == NULL)
79                 return FALSE;
80
81         while ((pch = strtok_r(NULL, ",", &last))) {
82                 if (g_str_has_prefix(partial_name, pch)) {
83                         BT_DBG("Match found\n");
84                         return TRUE;
85                 }
86         }
87         return FALSE;
88 }
89
90 gboolean _bt_agent_is_device_blacklist(const char *address,
91                 const char *name)
92 {
93         char *buffer;
94         char **lines;
95         int i;
96         FILE *fp;
97         long size;
98         long result;
99
100         BT_DBG("+");
101
102         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
103
104         if (fp == NULL) {
105                 BT_ERR("Unable to open blacklist file");
106                 return FALSE;
107         }
108
109         fseek(fp, 0, SEEK_END);
110         size = ftell(fp);
111         if (size <= 0) {
112                 BT_DBG("size is not a positive number");
113                 fclose(fp);
114                 return FALSE;
115         }
116
117         rewind(fp);
118
119         buffer = g_malloc0(sizeof(char) * size);
120         /* Fix : NULL_RETURNS */
121         if (buffer == NULL) {
122                 BT_ERR("Fail to allocate memory");
123                 fclose(fp);
124                 return FALSE;
125         }
126         result = fread((char *)buffer, 1, size, fp);
127         fclose(fp);
128         if (result != size) {
129                 BT_ERR("Read Error");
130                 g_free(buffer);
131                 return FALSE;
132         }
133
134         BT_DBG("Buffer = %s", buffer);
135
136         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
137         g_free(buffer);
138
139         if (lines == NULL) {
140                 BT_ERR("No lines in the file");
141                 return FALSE;
142         }
143
144         for (i = 0; lines[i] != NULL; i++) {
145                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
146                         if (__bt_agent_find_device_by_address_exactname(
147                                                 lines[i], address))
148                                 goto done;
149                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
150                         if (__bt_agent_find_device_by_address_exactname(
151                                                 lines[i], name))
152                                 goto done;
153                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
154                         if (__bt_agent_find_device_by_partial_name(lines[i],
155                                                 name))
156                                 goto done;
157                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
158                         if (__bt_agent_find_device_by_address_exactname(
159                                                 lines[i], address))
160                                 goto done;
161         }
162         g_strfreev(lines);
163         BT_DBG("-");
164         return FALSE;
165 done:
166         BT_DBG("Found the device");
167         g_strfreev(lines);
168         return TRUE;
169 }
170
171 void _bt_agent_release_memory(void)
172 {
173         /* Release Malloc Memory*/
174         malloc_trim(0);
175
176         /* Release Stack Memory*/
177         stack_trim();
178 }
179
180 gboolean _bt_agent_is_auto_response(unsigned int dev_class,
181                 const gchar *address, const gchar *name)
182 {
183         gboolean is_headset = FALSE;
184         gboolean is_mouse = FALSE;
185         char lap_address[BT_LOWER_ADDRESS_LENGTH];
186
187         BT_DBG("bt_agent_is_headset_class, [0x%02x] +", dev_class);
188
189         if (address == NULL)
190                 return FALSE;
191
192         switch ((dev_class & 0x1f00) >> 8) {
193         case 0x04:
194                 switch ((dev_class & 0xfc) >> 2) {
195                 case 0x01:
196                 case 0x02:
197                         /* Headset */
198                         is_headset = TRUE;
199                         break;
200                 case 0x06:
201                         /* Headphone */
202                         is_headset = TRUE;
203                         break;
204                 case 0x0b:      /* VCR */
205                 case 0x0c:      /* Video Camera */
206                 case 0x0d:      /* Camcorder */
207                         break;
208                 default:
209                         /* Other audio device */
210                         is_headset = TRUE;
211                         break;
212                 }
213                 break;
214         case 0x05:
215                 switch (dev_class & 0xff) {
216                 case 0x80:  /* 0x80: Pointing device(Mouse) */
217                         is_mouse = TRUE;
218                         break;
219
220                 case 0x40: /* 0x40: input device (BT keyboard) */
221                         /* Get the LAP(Lower Address part) */
222                         g_strlcpy(lap_address, address, sizeof(lap_address));
223
224                         /* Need to Auto pair the blacklisted Keyboard */
225                         if (_bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
226                                 BT_DBG("Device is not black listed\n");
227                                 return FALSE;
228                         } else {
229                                 BT_ERR("Device is black listed\n");
230                                 return TRUE;
231                         }
232                         break;
233                 default:
234                         break;
235                 }
236         default:
237                 break;
238         }
239
240         if ((!is_headset) && (!is_mouse))
241                 return FALSE;
242
243         /* Get the LAP(Lower Address part) */
244         g_strlcpy(lap_address, address, sizeof(lap_address));
245
246         BT_DBG("Device address = %s\n", address);
247         BT_DBG("Address 3 byte = %s\n", lap_address);
248
249         if (_bt_agent_is_device_blacklist(lap_address, name)) {
250                 BT_ERR("Device is black listed\n");
251                 return FALSE;
252         }
253         return TRUE;
254 }
255
256 int _bt_agent_generate_passkey(char *passkey, int size)
257 {
258         int i;
259         ssize_t len;
260         int random_fd;
261         unsigned int value = 0;
262
263         if (passkey == NULL)
264                 return -1;
265
266         if (size <= 0)
267                 return -1;
268
269         random_fd = open("/dev/urandom", O_RDONLY);
270
271         if (random_fd < 0)
272                 return -1;
273
274         for (i = 0; i < size; i++) {
275                 len = read(random_fd, &value, sizeof(value));
276                 if (len > 0)
277                         passkey[i] = '0' + (value % 10);
278         }
279         close(random_fd);
280         BT_DBG("passkey: %s", passkey);
281         return 0;
282 }