Implement RSSI scan filter
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / 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         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
135         g_free(buffer);
136
137         if (lines == NULL) {
138                 BT_ERR("No lines in the file");
139                 return FALSE;
140         }
141
142         for (i = 0; lines[i] != NULL; i++) {
143                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
144                         if (__bt_agent_find_device_by_address_exactname(
145                                                 lines[i], address))
146                                 goto done;
147                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
148                         if (__bt_agent_find_device_by_address_exactname(
149                                                 lines[i], name))
150                                 goto done;
151                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
152                         if (__bt_agent_find_device_by_partial_name(lines[i],
153                                                 name))
154                                 goto done;
155                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
156                         if (__bt_agent_find_device_by_address_exactname(
157                                                 lines[i], address))
158                                 goto done;
159         }
160         g_strfreev(lines);
161         BT_DBG("-");
162         return FALSE;
163 done:
164         BT_DBG("Found the device");
165         g_strfreev(lines);
166         return TRUE;
167 }
168
169 void _bt_agent_release_memory(void)
170 {
171         /* Release Malloc Memory*/
172         malloc_trim(0);
173
174         /* Release Stack Memory*/
175         stack_trim();
176 }
177
178 gboolean _bt_agent_is_auto_response(unsigned int dev_class,
179                 const gchar *address, const gchar *name)
180 {
181         gboolean is_headset = FALSE;
182         gboolean is_mouse = FALSE;
183         char lap_address[BT_LOWER_ADDRESS_LENGTH];
184
185         BT_DBG("bt_agent_is_headset_class, [0x%02x] +", dev_class);
186
187         if (address == NULL)
188                 return FALSE;
189
190         switch ((dev_class & 0x1f00) >> 8) {
191         case 0x04:
192                 switch ((dev_class & 0xfc) >> 2) {
193                 case 0x01:
194                 case 0x02:
195                         /* Headset */
196                         is_headset = TRUE;
197                         break;
198                 case 0x06:
199                         /* Headphone */
200                         is_headset = TRUE;
201                         break;
202                 case 0x0b:      /* VCR */
203                 case 0x0c:      /* Video Camera */
204                 case 0x0d:      /* Camcorder */
205                         break;
206                 default:
207                         /* Other audio device */
208                         is_headset = TRUE;
209                         break;
210                 }
211                 break;
212         case 0x05:
213                 switch (dev_class & 0xff) {
214                 case 0x80:  /* 0x80: Pointing device(Mouse) */
215                         is_mouse = TRUE;
216                         break;
217
218                 case 0x40: /* 0x40: input device (BT keyboard) */
219                         /* Get the LAP(Lower Address part) */
220                         g_strlcpy(lap_address, address, sizeof(lap_address));
221
222                         /* Need to Auto pair the blacklisted Keyboard */
223                         if (_bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
224                                 BT_DBG("Device is not black listed\n");
225                                 return FALSE;
226                         } else {
227                                 BT_ERR("Device is black listed\n");
228                                 return TRUE;
229                         }
230                         break;
231                 default:
232                         break;
233                 }
234         default:
235                 break;
236         }
237
238         if ((!is_headset) && (!is_mouse))
239                 return FALSE;
240
241         /* Get the LAP(Lower Address part) */
242         g_strlcpy(lap_address, address, sizeof(lap_address));
243
244         BT_DBG("Device address = %s\n", address);
245         BT_DBG("Address 3 byte = %s\n", lap_address);
246
247         if (_bt_agent_is_device_blacklist(lap_address, name)) {
248                 BT_ERR("Device is black listed\n");
249                 return FALSE;
250         }
251         return TRUE;
252 }
253
254 int _bt_agent_generate_passkey(char *passkey, int size)
255 {
256         int i;
257         ssize_t len;
258         int random_fd;
259         unsigned int value = 0;
260
261         if (passkey == NULL)
262                 return -1;
263
264         if (size <= 0)
265                 return -1;
266
267         random_fd = open("/dev/urandom", O_RDONLY);
268
269         if (random_fd < 0)
270                 return -1;
271
272         for (i = 0; i < size; i++) {
273                 len = read(random_fd, &value, sizeof(value));
274                 if (len > 0)
275                         passkey[i] = '0' + (value % 10);
276         }
277         close(random_fd);
278         BT_DBG("passkey: %s", passkey);
279         return 0;
280 }