Check if ckmc_get_data() provides NULL value
[platform/core/connectivity/net-config.git] / src / wifi-firmware.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <errno.h>
21 #include <vconf.h>
22 #include <vconf-keys.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <hal-wifi.h>
26
27 #include "log.h"
28 #include "util.h"
29 #include "wifi.h"
30 #include "netdbus.h"
31 #include "emulator.h"
32 #include "neterror.h"
33 #include "netsupplicant.h"
34 #include "wifi-firmware.h"
35 #include "network-statistics.h"
36
37 #define QUAD_CPUS_COUNT                 4
38 #define TEMP_BUFFER_LEN                 100
39 #define WIFI_MAC_ADD_PATH               "/sys/class/net/wlan0/address"
40
41 typedef struct {
42         char *interface_name;
43         enum netconfig_wifi_firmware type;
44 } wifi_driver_s;
45
46 static GSList *wifi_driver_list;
47
48 static void __netconfig_wifi_driver_free(gpointer data)
49 {
50         wifi_driver_s *driver = (wifi_driver_s *) data;
51
52         DBG("Remove wifi driver [%d:%s]", driver->type, driver->interface_name);
53
54         g_free(driver->interface_name);
55         g_free(driver);
56 }
57
58 static gint __netconfig_cmp_wifi_driver(gconstpointer a, gconstpointer b)
59 {
60         wifi_driver_s *drv_a = (wifi_driver_s *)a;
61         wifi_driver_s *drv_b = (wifi_driver_s *)b;
62
63         if (g_strcmp0(drv_a->interface_name, drv_b->interface_name))
64                 return -1;
65
66         return 0;
67 }
68
69 static GSList * __netconfig_is_wifi_driver_in_list(
70                 enum netconfig_wifi_firmware type, const char *interface_name)
71 {
72         wifi_driver_s driver = { .type = type, .interface_name = (char *)interface_name };
73         GSList *found = g_slist_find_custom(wifi_driver_list, &driver,
74                         __netconfig_cmp_wifi_driver);
75
76         return found;
77 }
78
79 static gboolean __netconfig_add_wifi_driver_to_list(
80                 enum netconfig_wifi_firmware type, const char *interface_name)
81 {
82         GSList *found;
83         wifi_driver_s *driver;
84
85         found = __netconfig_is_wifi_driver_in_list(type, interface_name);
86         if (found)
87                 return FALSE;
88
89         driver = g_try_new0(wifi_driver_s, 1);
90         if (!driver) {
91                 ERR("g_try_new0 failed!!!");
92                 return FALSE;
93         }
94
95         driver->interface_name = g_strdup(interface_name);
96         if (!driver->interface_name) {
97                 ERR("g_strdup failed!!!");
98                 g_free(driver);
99                 return FALSE;
100         }
101
102         driver->type = type;
103
104         wifi_driver_list = g_slist_prepend(wifi_driver_list, driver);
105         return TRUE;
106 }
107
108 static gboolean __netconfig_remove_wifi_driver_from_list(
109                 enum netconfig_wifi_firmware type, const char *interface_name)
110 {
111         GSList *found;
112
113         found = __netconfig_is_wifi_driver_in_list(type, interface_name);
114         if (!found)
115                 return FALSE;
116
117         __netconfig_wifi_driver_free(found->data);
118         wifi_driver_list = g_slist_delete_link(wifi_driver_list, found);
119
120         return TRUE;
121 }
122
123 static int __netconfig_sta_firmware_start(const char *interface_name)
124 {
125         int rv = 0;
126         int if_found = 0;
127
128         if_found = wifi_check_interface(interface_name);
129
130         rv = hal_wifi_sta_start(interface_name);
131         if (rv < 0 && !if_found) {
132                 DBG("hal_wifi_sta_start() failed, ret: %d", rv);
133                 return -EIO;
134         }
135
136         rv = netconfig_interface_up(interface_name);
137         if (rv != TRUE)
138                 return -EIO;
139
140         DBG("Successfully loaded wireless device driver");
141         return 0;
142 }
143
144 static int __netconfig_sta_firmware_stop(const char *interface_name)
145 {
146         int rv = 0;
147
148         rv = netconfig_interface_down(interface_name);
149         if (rv != TRUE)
150                 return -EIO;
151
152         rv = hal_wifi_stop(interface_name);
153         if (rv < 0) {
154                 DBG("hal_wifi_stop() failed, ret: %d", rv);
155                 netconfig_interface_up(interface_name);
156                 return -EIO;
157         }
158
159         DBG("Successfully removed wireless device driver");
160         return 0;
161 }
162
163 static int __netconfig_p2p_firmware_start(const char *interface_name)
164 {
165         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT))
166                 return -ENODEV;
167
168         int rv = 0;
169         int if_found = 0;
170
171         if_found = wifi_check_interface(interface_name);
172
173         rv = hal_wifi_p2p_start(interface_name);
174         if (rv < 0 && !if_found) {
175                 DBG("hal_wifi_p2p_start() failed, ret: %d", rv);
176                 return -EIO;
177         }
178
179 #if defined TIZEN_WLAN_USE_P2P_INTERFACE
180         rv = netconfig_interface_up(interface_name);
181         if (rv != TRUE)
182                 return -EIO;
183 #endif
184
185         DBG("Successfully loaded p2p device driver");
186         return 0;
187 }
188
189 static int __netconfig_p2p_firmware_stop(const char *interface_name)
190 {
191         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT))
192                 return -ENODEV;
193
194         int rv = 0;
195
196         rv = netconfig_interface_down(interface_name);
197         if (rv != TRUE)
198                 return -EIO;
199
200         rv = hal_wifi_stop(interface_name);
201         if (rv < 0) {
202                 DBG("hal_wifi_stop() failed, ret: %d", rv);
203                 netconfig_interface_up(interface_name);
204                 return -EIO;
205         }
206
207         DBG("Successfully removed p2p device driver");
208         return 0;
209 }
210
211 static int __netconfig_softap_firmware_start(const char *interface_name)
212 {
213         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING)
214                         && !netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP))
215                 return -ENODEV;
216
217         int rv = 0;
218         int if_found = 0;
219
220         if_found = wifi_check_interface(interface_name);
221
222         rv = hal_wifi_softap_start(interface_name);
223         if (rv < 0 && !if_found) {
224                 DBG("hal_wifi_softap_start() failed, ret: %d", rv);
225                 return -EIO;
226         }
227
228         if (netconfig_interface_up(interface_name) == FALSE)
229                 return -EIO;
230
231         DBG("Successfully loaded softap device driver");
232         return 0;
233 }
234
235 static int __netconfig_softap_firmware_stop(const char *interface_name)
236 {
237         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING)
238                         && !netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP))
239                 return -ENODEV;
240
241         int rv = 0;
242
243         rv = netconfig_interface_down(interface_name);
244         if (rv != TRUE)
245                 return -EIO;
246
247         rv = hal_wifi_stop(interface_name);
248         if (rv < 0) {
249                 DBG("hal_wifi_stop() failed, ret: %d", rv);
250                 netconfig_interface_up(interface_name);
251                 return -EIO;
252         }
253
254         DBG("Successfully removed softap device driver");
255         return 0;
256 }
257
258 static int __netconfig_wifi_firmware_start(enum netconfig_wifi_firmware type,
259                 const char *interface_name)
260 {
261         if (emulator_is_emulated() == TRUE)
262                 return -EIO;
263
264         switch (type) {
265         case NETCONFIG_WIFI_STA:
266                 return __netconfig_sta_firmware_start(interface_name);
267         case NETCONFIG_WIFI_P2P:
268                 return __netconfig_p2p_firmware_start(interface_name);
269         case NETCONFIG_WIFI_SOFTAP:
270                 return __netconfig_softap_firmware_start(interface_name);
271         default:
272                 break;
273         }
274
275         return -ENXIO;
276 }
277
278 static int __netconfig_wifi_firmware_stop(enum netconfig_wifi_firmware type,
279                 const char *interface_name)
280 {
281         if (emulator_is_emulated() == TRUE)
282                 return -EIO;
283
284         switch (type) {
285         case NETCONFIG_WIFI_STA:
286                 return __netconfig_sta_firmware_stop(interface_name);
287         case NETCONFIG_WIFI_P2P:
288                 return __netconfig_p2p_firmware_stop(interface_name);
289         case NETCONFIG_WIFI_SOFTAP:
290                 return __netconfig_softap_firmware_stop(interface_name);
291         default:
292                 break;
293         }
294
295         return -ENXIO;
296 }
297
298 static int __netconfig_set_rps_cpus(const char *interface_name)
299 {
300         int fd, curr;
301         ssize_t count;
302         char t_buf[TEMP_BUFFER_LEN];
303         char r_buf[TEMP_BUFFER_LEN];
304
305         if (access(WIFI_MAC_ADD_PATH, F_OK) != 0) {
306                 DBG("WiFi driver is not loaded... ");
307                 return -1;
308         } else {
309                 DBG("WiFi driver loaded... ");
310         }
311
312         snprintf(t_buf, TEMP_BUFFER_LEN,
313                 "/sys/class/net/%s/queues/rx-0/rps_cpus",
314                 interface_name);
315         DBG("Command : [%s]", t_buf);
316         curr = 0;
317
318         while ((fd = open(t_buf, O_RDWR | O_CLOEXEC)) >= 0) {
319                 curr++;
320                 count = read(fd, r_buf, 1);
321
322                 if (count < 0) {
323                         DBG("read failed");
324                         close(fd);
325                         return -1;
326                 } else {
327                         DBG("read size = %zd", count);
328                 }
329
330                 if (r_buf[0] == 'e') {
331                         close(fd);
332                         DBG("e is already written");
333                         snprintf(t_buf, TEMP_BUFFER_LEN,
334                                 "/sys/class/net/%s/queues/rx-%d/rps_cpus",
335                                 interface_name, curr);
336                         DBG("Command : [%s]", t_buf);
337                         continue;
338                 } else {
339                         DBG("writing e");
340                 }
341
342                 if (lseek(fd, 0, SEEK_SET) < 0) {
343                         DBG("lseek failed");
344                         close(fd);
345                         return -1;
346                 }
347
348                 count = write(fd, "e", 1);
349
350                 if (count < 0) {
351                         DBG("write failed");
352                         close(fd);
353                         return -1;
354                 } else {
355                         DBG("write size = %zd", count);
356                 }
357
358                 close(fd);
359                 snprintf(t_buf, TEMP_BUFFER_LEN,
360                         "/sys/class/net/%s/queues/rx-%d/rps_cpus",
361                         interface_name, curr);
362                 DBG("Command : [%s]", t_buf);
363         }
364
365         return 0;
366 }
367
368 int netconfig_wifi_firmware_get_mac(const char *interface_name, char **mac)
369 {
370         int rv = 0;
371
372         rv = hal_wifi_get_mac(interface_name, mac);
373         if (rv < 0) {
374                 DBG("hal_wifi_get_mac() failed, ret: %d", rv);
375                 return -EIO;
376         }
377
378         DBG("Successfully loaded default wifi mac address: %s", *mac);
379         return 0;
380 }
381
382 int netconfig_wifi_firmware(enum netconfig_wifi_firmware type,
383                 const char *interface_name, gboolean enable)
384 {
385         int err;
386
387         DBG("Wi-Fi firmware (type: %d %s) for %s", type, enable == TRUE ? "enable" : "disable",
388                         interface_name ? interface_name : "");
389
390         GSList *found = __netconfig_is_wifi_driver_in_list(type, interface_name);
391
392         if (enable == FALSE) {
393                 wifi_driver_s *driver;
394
395                 if (!found)
396                         return -EALREADY;
397
398                 driver = (wifi_driver_s *) found->data;
399
400                 if (type != driver->type)
401                         return -EIO;
402
403                 err = __netconfig_wifi_firmware_stop(type, interface_name);
404                 if (err < 0 && err != -EALREADY)
405                         return err;
406
407                 __netconfig_remove_wifi_driver_from_list(type, interface_name);
408
409                 return err;
410         }
411
412         if (found) {
413                 wifi_driver_s *driver = (wifi_driver_s *) found->data;
414
415                 DBG("Wi-Fi interface (%s) already in use", interface_name);
416
417                 if (type == driver->type)
418                         return -EALREADY;
419
420                 return -EIO;
421         }
422
423         err = __netconfig_wifi_firmware_start(type, interface_name);
424         if (err < 0)
425                 DBG("Failed to execute script file");
426         else
427                 __netconfig_add_wifi_driver_to_list(type, interface_name);
428
429         if (__netconfig_set_rps_cpus(interface_name) < 0)
430                 DBG("Failed to set rps_cpus");
431
432         return err;
433 }
434
435 gboolean handle_start(WifiFirmware *firmware, GDBusMethodInvocation *context,
436                 const gchar *device, const gchar *ifname)
437 {
438         int err;
439
440         g_return_val_if_fail(firmware != NULL, TRUE);
441
442         DBG("Wi-Fi firmware start %s", device != NULL ? device : "null");
443
444         if (g_strcmp0("p2p", device) == 0)
445                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, ifname, TRUE);
446         else if (g_strcmp0("softap", device) == 0)
447                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, ifname, TRUE);
448         else
449                 err = -EINVAL;
450
451         if (err < 0) {
452                 if (err == -EALREADY)
453                         netconfig_error_already_exists(context);
454                 else if (g_strcmp0("softap", device) == 0 &&
455                         err == -EIO && netconfig_is_wifi_direct_on() == FALSE) {
456                         if (netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, ifname, FALSE) == 0 &&
457                                 netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, ifname, TRUE) == 0) {
458                                 wifi_firmware_complete_start(firmware, context);
459                                 return TRUE;
460                         } else
461                                 netconfig_error_wifi_driver_failed(context);
462                 } else
463                         netconfig_error_wifi_driver_failed(context);
464
465                 return TRUE;
466         }
467
468         wifi_firmware_complete_start(firmware, context);
469         return TRUE;
470 }
471
472 gboolean handle_stop(WifiFirmware *firmware, GDBusMethodInvocation *context,
473                 const gchar *device, const gchar *ifname)
474 {
475         int err;
476
477         g_return_val_if_fail(firmware != NULL, TRUE);
478
479         DBG("Wi-Fi firmware stop %s", device != NULL ? device : "null");
480
481         if (g_strcmp0("p2p", device) == 0)
482                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_P2P, ifname, FALSE);
483         else if (g_strcmp0("softap", device) == 0)
484                 err = netconfig_wifi_firmware(NETCONFIG_WIFI_SOFTAP, ifname, FALSE);
485         else
486                 err = -EINVAL;
487
488         if (err < 0) {
489                 if (err == -EALREADY)
490                         netconfig_error_already_exists(context);
491                 else
492                         netconfig_error_wifi_driver_failed(context);
493
494                 return TRUE;
495         }
496
497         wifi_firmware_complete_stop(firmware, context);
498         return TRUE;
499 }