1 /*--------------------------------------------------------------------------
2 Copyright (c) 2013, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <dirent.h>
35 #include <ctype.h>
36 #include <grp.h>
37 #include <utime.h>
38 #include <sys/stat.h>
39 #include <sys/sendfile.h>
40 #define LOG_TAG "wcnss_service"
41 #include <cutils/log.h>
42 #include <cutils/properties.h>
43 #ifdef WCNSS_QMI
44 #include "wcnss_qmi_client.h"
45 #include "mdm_detect.h"
46 #endif
47
48 #define SUCCESS 0
49 #define FAILED -1
50 #define BYTE_0 0
51 #define BYTE_1 8
52 #define BYTE_2 16
53 #define BYTE_3 24
54 #define UNUSED(x) (void)(x)
55
56 #define MAX_FILE_LENGTH (1024)
57 #define WCNSS_MAX_CMD_LEN (128)
58
59 /* control messages to wcnss driver */
60 #define WCNSS_USR_CTRL_MSG_START 0x00000000
61 #define WCNSS_USR_SERIAL_NUM (WCNSS_USR_CTRL_MSG_START + 1)
62 #define WCNSS_USR_HAS_CAL_DATA (WCNSS_USR_CTRL_MSG_START + 2)
63 #define WCNSS_USR_WLAN_MAC_ADDR (WCNSS_USR_CTRL_MSG_START + 3)
64
65
66 #define WCNSS_CAL_CHUNK (3*1024)
67 #define WCNSS_CAL_FILE "/data/vendor/wifi/WCNSS_qcom_wlan_cal.bin"
68 #define WCNSS_FACT_FILE "/data/vendor/wifi/WCN_FACTORY"
69 #define WCNSS_DEVICE "/dev/wcnss_wlan"
70 #define WCNSS_CTRL "/dev/wcnss_ctrl"
71 #define WLAN_INI_FILE_DEST "/data/vendor/wifi/WCNSS_qcom_cfg.ini"
72 #define WLAN_INI_FILE_SOURCE "/vendor/etc/wifi/WCNSS_qcom_cfg.ini"
73 #define WCNSS_HAS_CAL_DATA\
74 "/sys/module/wcnsscore/parameters/has_calibrated_data"
75 #define WLAN_DRIVER_ATH_DEFAULT_VAL "0"
76
77 #define ASCII_A 65
78 #define ASCII_a 97
79 #define ASCII_0 48
80 #define HEXA_A 10
81 #define HEX_BASE 16
82
83 #ifdef WCNSS_QMI
84 #define WLAN_ADDR_SIZE 6
85 unsigned char wlan_nv_mac_addr[WLAN_ADDR_SIZE];
86 #define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
87 #define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x"
88
89 /* As we Want to write in 00:0a:f5:11:22:33 format in sysfs file
90 so taking mac length as 12 char + 5 for ":" + NULL
91 */
92 #define WLAN_MAC_ADDR_STRING 18
93 #endif
94
95 #define MAX_SOC_INFO_NAME_LEN (15)
96 #define MAX_DATA_NVBIN_PATH_LEN (64)
97 #define QRD_DYNAMIC_NV_PROP "persist.sys.dynamic.nv"
98 #define QRD_HW_PLATFORM "QRD"
99 #define QRD_PLATFORM_SUBTYPE_ID 0
100 #define PERSIST_NVFILE "/persist/WCNSS_qcom_wlan_nv.bin"
101 #define DATA_NVFILE_DIR "/data/misc/wifi/nvbin/"
102 #define SYSFS_SOCID_PATH1 "/sys/devices/soc0/soc_id"
103 #define SYSFS_SOCID_PATH2 "/sys/devices/system/soc/soc0/id"
104 #define SYSFS_HW_PLATFORM_PATH1 "/sys/devices/soc0/hw_platform"
105 #define SYSFS_HW_PLATFORM_PATH2 "/sys/devices/system/soc/soc0/hw_platform"
106 #define SYSFS_PLATFORM_SUBTYPE_PATH1 "/sys/devices/soc0/platform_subtype_id"
107 #define SYSFS_PLATFORM_SUBTYPE_PATH2 "/sys/devices/system/soc/soc0/platform_subtype_id"
108 #define SYSFS_PLATFORM_VERSION_PATH1 "/sys/devices/soc0/platform_version"
109 #define SYSFS_PLATFORM_VERSION_PATH2 "/sys/devices/system/soc/soc0/platform_version"
110 #define SOCINFO_HWVER_MAJOR(ver) (((ver) & 0x00ff0000) >> 16)
111 #define SOCINFO_HWVER_MINOR(ver) ((ver) & 0x000000ff)
112 #define GET_SOC_INFO(buf, soc_node_path1, soc_node_path2, info_got) \
113 { if (get_soc_info(buf, soc_node_path1, soc_node_path2) < 0) \
114 { \
115 ALOGE("get_soc_info failed!\n"); \
116 return FAILED; \
117 } \
118 info_got = atoi(buf); \
119 }
120
wcnss_write_cal_data(int fd_dev)121 int wcnss_write_cal_data(int fd_dev)
122 {
123 int rcount = 0;
124 int size = 0;
125 int rc = 0;
126 int wcount = 0;
127 int fd_file;
128 struct stat st;
129
130 char buf[WCNSS_CAL_CHUNK];
131
132 ALOGI("wcnss_write_cal_data trying to write cal");
133
134 rc = stat(WCNSS_CAL_FILE, &st);
135 if (rc < 0) {
136 ALOGE("Failed to stat cal file : %s",
137 strerror(errno));
138 goto exit;
139 }
140
141 size = st.st_size;
142
143 fd_file = open(WCNSS_CAL_FILE, O_RDONLY);
144 if (fd_file < 0) {
145 ALOGE("cal file doesn't exist: %s",
146 strerror(errno));
147 rc = fd_file;
148 goto exit;
149 }
150
151 /* write the file size first, so that platform driver knows
152 * when it recieves the full data */
153 wcount = write(fd_dev, (void *)&size, 4);
154 if (wcount != 4) {
155 ALOGE("Failed to write to wcnss device : %s",
156 strerror(errno));
157 rc = wcount;
158 goto exit_close;
159 }
160
161 do {
162 rcount = read(fd_file, (void *)buf, sizeof(buf));
163 if (rcount < 0) {
164 ALOGE("Failed to read from cal file ; %s",
165 strerror(errno));
166 rc = rcount;
167 goto exit_remove;
168 }
169
170 if (!rcount)
171 break;
172
173 wcount = write(fd_dev, buf, rcount);
174 if (wcount < 0) {
175 ALOGE("Failed to write to wcnss device : %s",
176 strerror(errno));
177 rc = wcount;
178 goto exit_close;
179 }
180
181 } while (rcount);
182 close(fd_file);
183
184 return SUCCESS;
185
186 exit_remove:
187 close(fd_file);
188 remove("WCNSS_CAL_FILE");
189 return rc;
190
191 exit_close:
192 close(fd_file);
193
194 exit:
195 return rc;
196 }
197
198
wcnss_read_and_store_cal_data(int fd_dev)199 int wcnss_read_and_store_cal_data(int fd_dev)
200 {
201 int rcount = 0;
202 int wcount = 0;
203 int fd_file = -1;
204 int rc = 0;
205
206 char buf[WCNSS_CAL_CHUNK];
207
208 ALOGI("wcnss_read_and_store_cal_data trying to read cal");
209
210 do {
211 /* wait on this read until data comes from fw */
212 rcount = read(fd_dev, (void *)buf, sizeof(buf));
213 if (rcount < 0) {
214 ALOGE("Failed to read from wcnss device : %s",
215 strerror(errno));
216 rc = rcount;
217 goto exit;
218 }
219
220 /* truncate the file only if there is fw data, this read
221 * may never return if the fw decides that no more cal is
222 * required; and the data we have now is good enough.
223 */
224 if (fd_file < 0) {
225 fd_file = open(WCNSS_CAL_FILE, O_WRONLY
226 | O_CREAT | O_TRUNC, 0664);
227 if (fd_file < 0) {
228 ALOGE("Failed to open cal file : %s",
229 strerror(errno));
230 rc = fd_file;
231 goto exit;
232 }
233 }
234
235 if (!rcount)
236 break;
237
238 wcount = write(fd_file, buf, rcount);
239 if (wcount < 0) {
240 ALOGE("Failed to write to cal file : %s",
241 strerror(errno));
242 rc = wcount;
243 goto exit_remove;
244 }
245
246 } while (rcount);
247
248 close(fd_file);
249
250 return SUCCESS;
251
252 exit_remove:
253 close(fd_file);
254 remove(WCNSS_CAL_FILE);
255
256 exit:
257 return rc;
258 }
259
260
find_full_path(char * cur_dir,char * file_to_find,char * full_path)261 void find_full_path(char *cur_dir, char *file_to_find, char *full_path)
262 {
263 DIR *dir;
264 struct stat st;
265 struct dirent *dr;
266 char cwd[1024];
267 int rc;
268
269 chdir(cur_dir);
270
271 dir = opendir(".");
272
273 if (dir != NULL) {
274 while ((dr = readdir(dir))) {
275
276 rc = lstat(dr->d_name, &st);
277 if (rc < 0) {
278 ALOGE("lstat failed %s", strerror(errno));
279 return;
280 }
281 if (S_ISDIR(st.st_mode)) {
282 if ((strcmp(dr->d_name, ".")) &&
283 (strcmp(dr->d_name, ".."))) {
284 find_full_path(dr->d_name,
285 file_to_find, full_path);
286 }
287 } else if (!strcmp(file_to_find, dr->d_name)) {
288 getcwd(cwd, sizeof(cwd));
289 snprintf(full_path, MAX_FILE_LENGTH, "%s/%s",
290 cwd, file_to_find);
291 }
292 }
293 closedir(dir);
294 }
295
296 chdir("..");
297 }
298
setup_wlan_config_file()299 void setup_wlan_config_file()
300 {
301 int rfd;
302 int wfd;
303 struct stat st_dest, st_src;
304 int rc_dest;
305 int rc;
306 struct group *grp;
307 struct utimbuf new_time;
308
309 rc = stat(WLAN_INI_FILE_SOURCE, &st_src);
310 if (rc != 0) {
311 ALOGE("source file do not exist %s", WLAN_INI_FILE_SOURCE);
312 return;
313 }
314
315 rc_dest = stat(WLAN_INI_FILE_DEST, &st_dest);
316 if (rc_dest == 0 && st_dest.st_size &&
317 (st_dest.st_mtime > st_src.st_mtime)) {
318 ALOGE("wlan ini file exists %s and is newer than %s",
319 WLAN_INI_FILE_DEST, WLAN_INI_FILE_SOURCE);
320 goto out_nocopy;
321 }
322
323 rfd = open(WLAN_INI_FILE_SOURCE, O_RDONLY);
324 if (rfd < 0) {
325 ALOGE("Failed to open ini source file: %s", strerror(errno));
326 return;
327 }
328
329 wfd = open(WLAN_INI_FILE_DEST, O_WRONLY | O_CREAT | O_TRUNC, 0660);
330 if (wfd < 0) {
331 ALOGE("Failed to open ini dest file: %s", strerror(errno));
332 close(rfd);
333 return;
334 }
335
336 rc = sendfile(wfd, rfd, 0, st_src.st_size);
337 if (rc != st_src.st_size) {
338 ALOGE("Failed to copy ini file: %s", strerror(errno));
339 goto out;
340 }
341
342 new_time.actime = st_src.st_atime;
343 new_time.modtime = st_src.st_mtime;
344
345 rc = utime(WLAN_INI_FILE_DEST, &new_time);
346 if (rc != 0)
347 ALOGE("could not preserve the timestamp %s", strerror(errno));
348
349 grp = getgrnam("wifi");
350 if (grp != NULL) {
351 rc = chown(WLAN_INI_FILE_DEST, -1, grp->gr_gid);
352 if (rc != 0)
353 ALOGE("Failed change group of ini file %s", strerror(errno));
354 } else {
355 ALOGE("Failed to get group wifi %s", strerror(errno));
356 }
357
358 property_set("vendor.wlan.driver.config", WLAN_INI_FILE_DEST);
359
360 out:
361 close(rfd);
362 close(wfd);
363 return;
364
365 out_nocopy:
366 property_set("vendor.wlan.driver.config", WLAN_INI_FILE_DEST);
367 return;
368 }
convert_string_to_hex(char * string)369 unsigned int convert_string_to_hex(char* string)
370 {
371 int idx;
372 unsigned long int hex_num = 0;
373 for(idx = 0; string[idx] != '\0'; idx++){
374 if(isalpha(string[idx])) {
375 if(string[idx] >='a' && string[idx] <='f') {
376 hex_num = hex_num * HEX_BASE + ((int)string[idx]
377 - ASCII_a + HEXA_A);
378 } else if ( string[idx] >='A' && string[idx] <='F') {
379 hex_num = hex_num * HEX_BASE + ((int)string[idx]
380 - ASCII_A + HEXA_A);
381 } else
382 hex_num = hex_num * HEX_BASE + (int)string[idx];
383 } else {
384 hex_num = hex_num * HEX_BASE + (string[idx]- ASCII_0);
385 }
386 }
387 hex_num = hex_num & 0xFFFFFFFF;
388 return hex_num;
389 }
390
391
392 #ifdef WCNSS_QMI
setup_wcnss_parameters(int * cal,int nv_mac_addr)393 void setup_wcnss_parameters(int *cal, int nv_mac_addr)
394 #else
395 void setup_wcnss_parameters(int *cal)
396 #endif
397 {
398 char msg[WCNSS_MAX_CMD_LEN];
399 char serial[PROPERTY_VALUE_MAX];
400 int fd, rc, pos = 0;
401 struct stat st;
402 unsigned int serial_num = 0;
403
404 fd = open(WCNSS_CTRL, O_WRONLY);
405 if (fd < 0) {
406 ALOGE("Failed to open %s : %s", WCNSS_CTRL, strerror(errno));
407 return;
408 }
409
410 rc = property_get("ro.serialno", serial, "");
411 if (rc) {
412 serial_num = convert_string_to_hex(serial);
413 ALOGE("Serial Number is %x", serial_num);
414
415 msg[pos++] = WCNSS_USR_SERIAL_NUM >> BYTE_1;
416 msg[pos++] = WCNSS_USR_SERIAL_NUM >> BYTE_0;
417 msg[pos++] = serial_num >> BYTE_3;
418 msg[pos++] = serial_num >> BYTE_2;
419 msg[pos++] = serial_num >> BYTE_1;
420 msg[pos++] = serial_num >> BYTE_0;
421
422 if (write(fd, msg, pos) < 0) {
423 ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
424 strerror(errno));
425 goto fail;
426 }
427 }
428
429 #ifdef WCNSS_QMI
430 if (SUCCESS == nv_mac_addr)
431 {
432 pos = 0;
433 msg[pos++] = WCNSS_USR_WLAN_MAC_ADDR >> BYTE_1;
434 msg[pos++] = WCNSS_USR_WLAN_MAC_ADDR >> BYTE_0;
435 msg[pos++] = wlan_nv_mac_addr[0];
436 msg[pos++] = wlan_nv_mac_addr[1];
437 msg[pos++] = wlan_nv_mac_addr[2];
438 msg[pos++] = wlan_nv_mac_addr[3];
439 msg[pos++] = wlan_nv_mac_addr[4];
440 msg[pos++] = wlan_nv_mac_addr[5];
441
442 ALOGI("WLAN MAC Addr:" MAC_ADDRESS_STR,
443 MAC_ADDR_ARRAY(wlan_nv_mac_addr));
444
445 if (write(fd, msg, pos) < 0) {
446 ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
447 strerror(errno));
448 goto fail;
449 }
450 }
451 #endif
452
453 pos = 0;
454 msg[pos++] = WCNSS_USR_HAS_CAL_DATA >> BYTE_1;
455 msg[pos++] = WCNSS_USR_HAS_CAL_DATA >> BYTE_0;
456
457 rc = stat(WCNSS_FACT_FILE, &st);
458 if (rc == 0) {
459 ALOGE("Factory file found, deleting cal file");
460 unlink(WCNSS_CAL_FILE);
461 goto fail_resp;
462 }
463
464 rc = stat(WCNSS_CAL_FILE, &st);
465 if (rc != 0) {
466 ALOGE("CAL file not found");
467 goto fail_resp;
468 }
469
470 /* has cal data */
471 msg[pos++] = 1;
472
473 if (write(fd, msg, pos) < 0) {
474 ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
475 strerror(errno));
476 goto fail;
477 }
478
479 ALOGI("Correctly triggered cal file");
480 *cal = SUCCESS;
481 close(fd);
482 return;
483
484 fail_resp:
485 msg[pos++] = 0;
486 if (write(fd, msg, pos) < 0)
487 ALOGE("Failed to write to %s : %s", WCNSS_CTRL,
488 strerror(errno));
489
490 fail:
491 *cal = FAILED;
492 close(fd);
493 return;
494 }
495
setup_wlan_driver_ath_prop()496 void setup_wlan_driver_ath_prop()
497 {
498 property_set("vendor.wlan.driver.ath", WLAN_DRIVER_ATH_DEFAULT_VAL);
499 }
500
501 #ifdef WCNSS_QMI
check_modem_compatability(struct dev_info * mdm_detect_info)502 int check_modem_compatability(struct dev_info *mdm_detect_info)
503 {
504 char args[MODEM_BASEBAND_PROPERTY_SIZE] = {0};
505 int ret = 0;
506 /* Get the hardware property */
507 ret = property_get(MODEM_BASEBAND_PROPERTY, args, "");
508 if (ret > MODEM_BASEBAND_PROPERTY_SIZE) {
509 ALOGE("property [%s] has size [%d] that exceeds max [%d]",
510 MODEM_BASEBAND_PROPERTY, ret, MODEM_BASEBAND_PROPERTY_SIZE);
511 return 0;
512 }
513 /* This will check for the type of hardware, and if the
514 hardware type needs external modem, it will check if the
515 modem type is external*/
516 if(!strncmp(MODEM_BASEBAND_VALUE_APQ, args, 3)) {
517
518 for (ret = 0; ret < mdm_detect_info->num_modems; ret++) {
519 if (mdm_detect_info->mdm_list[ret].type == MDM_TYPE_EXTERNAL) {
520 ALOGE("Hardware supports external modem");
521 return 1;
522 }
523 }
524 ALOGE("Hardware does not support external modem");
525 return 0;
526 }
527 return 1;
528 }
529 #endif
530
read_line_from_file(const char * path,char * buf,size_t count)531 static int read_line_from_file(const char *path, char *buf, size_t count)
532 {
533 char * fgets_ret;
534 FILE * fd;
535 int rv;
536
537 fd = fopen(path, "r");
538 if (fd == NULL)
539 return -1;
540
541 fgets_ret = fgets(buf, (int)count, fd);
542 if (NULL != fgets_ret) {
543 rv = (int)strlen(buf);
544 } else {
545 rv = ferror(fd);
546 }
547
548 fclose(fd);
549
550 return rv;
551 }
552
get_soc_info(char * buf,char * soc_node_path1,char * soc_node_path2)553 static int get_soc_info(char *buf, char *soc_node_path1,
554 char *soc_node_path2)
555 {
556 int ret = 0;
557
558 ret = read_line_from_file(soc_node_path1, buf,
559 MAX_SOC_INFO_NAME_LEN);
560 if (ret < 0) {
561 ret = read_line_from_file(soc_node_path2, buf,
562 MAX_SOC_INFO_NAME_LEN);
563 if (ret < 0) {
564 ALOGE("getting socinfo(%s, %d) failed.\n",
565 soc_node_path1, ret);
566 return ret;
567 }
568 }
569 if (ret && buf[ret - 1] == '\n')
570 buf[ret - 1] = '\0';
571
572 return ret;
573 }
574
get_data_nvfile_path(char * data_nvfile_path,struct stat * pdata_nvfile_stat)575 static int get_data_nvfile_path(char *data_nvfile_path,
576 struct stat *pdata_nvfile_stat)
577 {
578 char target_board_platform[PROP_VALUE_MAX] = {'\0'};
579 char buf[MAX_SOC_INFO_NAME_LEN] = {'\0'};
580 int soc_id, platform_subtype_id, platform_version;
581 int major_hwver, minor_hwver;
582 int rc;
583
584 rc = property_get("ro.board.platform", target_board_platform, "");
585 if (!rc)
586 {
587 ALOGE("get ro.board.platform fail, rc=%d(%s)\n",
588 rc, strerror(errno));
589 return FAILED;
590 }
591
592 GET_SOC_INFO(buf, SYSFS_SOCID_PATH1, SYSFS_SOCID_PATH2, soc_id);
593 GET_SOC_INFO(buf, SYSFS_PLATFORM_SUBTYPE_PATH1,
594 SYSFS_PLATFORM_SUBTYPE_PATH2, platform_subtype_id);
595 GET_SOC_INFO(buf, SYSFS_PLATFORM_VERSION_PATH1,
596 SYSFS_PLATFORM_VERSION_PATH2, platform_version);
597
598 major_hwver = SOCINFO_HWVER_MAJOR(platform_version);
599 minor_hwver = SOCINFO_HWVER_MINOR(platform_version);
600
601 snprintf(data_nvfile_path, MAX_DATA_NVBIN_PATH_LEN,
602 "%s%s_%d_0x%02x_0x%02x_0x%02x_nv.bin", DATA_NVFILE_DIR,
603 target_board_platform, soc_id, platform_subtype_id&0xff,
604 major_hwver&0xff, minor_hwver&0xff);
605 ALOGI("data_nvfile_path %s\n",
606 data_nvfile_path);
607
608 if (stat(data_nvfile_path, pdata_nvfile_stat) != 0)
609 {
610 ALOGE("source file do not exist %s\n",
611 data_nvfile_path);
612 return FAILED;
613 }
614
615 return SUCCESS;
616 }
617
nvbin_sendfile(const char * dst,const char * src,struct stat * src_stat)618 static int nvbin_sendfile(const char *dst, const char *src,
619 struct stat *src_stat)
620 {
621 struct utimbuf new_time;
622 int fp_src, fp_dst;
623 int rc;
624 if ((fp_src = open(src, O_RDONLY)) < 0)
625 {
626 ALOGE("open %s failed(%s).\n",
627 src, strerror(errno));
628 return FAILED;
629 }
630
631 if ((fp_dst = open(dst, O_WRONLY |O_TRUNC)) < 0)
632 {
633 close(fp_src);
634 ALOGE("open %s failed(%s).\n",
635 dst, strerror(errno));
636 return FAILED;
637 }
638
639 if (sendfile(fp_dst, fp_src, 0, src_stat->st_size) == -1)
640 {
641 ALOGE("dynamic nv sendfile failed: (%s).\n",
642 strerror(errno));
643 rc = FAILED;
644 goto exit;
645 }
646
647 new_time.actime = src_stat->st_atime;
648 new_time.modtime = src_stat->st_mtime;
649 if (utime(dst, &new_time) != 0)
650 {
651 ALOGE("could not preserve the timestamp %s",
652 strerror(errno));
653 rc = FAILED;
654 goto exit;
655 }
656
657 rc = SUCCESS;
658 exit:
659 close(fp_dst);
660 close(fp_src);
661 return rc;
662 }
dynamic_nv_replace()663 void dynamic_nv_replace()
664 {
665 char data_nvfile_path[MAX_DATA_NVBIN_PATH_LEN] = {'\0'};
666 char property_nv_replaced_status [PROPERTY_VALUE_MAX] = { '\0' };
667 char buf[MAX_SOC_INFO_NAME_LEN] = {'\0'};
668 struct stat data_nvfile_stat;
669 int rc;
670
671 if (property_get(QRD_DYNAMIC_NV_PROP, property_nv_replaced_status, NULL)
672 && strcmp(property_nv_replaced_status, "done") == 0) {
673 ALOGI("dynamic nv have been replaced. leave\n");
674 return;
675 }
676
677 rc = get_soc_info(buf, SYSFS_HW_PLATFORM_PATH1, SYSFS_HW_PLATFORM_PATH2);
678 if (rc < 0)
679 {
680 ALOGE("get_soc_info(HW_PLATFORM) fail!\n");
681 return;
682 } else {
683 if( 0 != strncmp(buf, QRD_HW_PLATFORM, MAX_SOC_INFO_NAME_LEN))
684 {
685 ALOGI("dynamic nv only for QRD platform, current platform:%s.\n",
686 buf);
687 return;
688 }
689 }
690
691 rc = get_data_nvfile_path(data_nvfile_path, &data_nvfile_stat);
692 if (rc != SUCCESS)
693 {
694 ALOGE("Get source file path fail !\n");
695 return;
696 }
697
698 if (property_set(QRD_DYNAMIC_NV_PROP, "replacing") < 0)
699 {
700 ALOGE("set %s to replacing failed (%s).\n",
701 QRD_DYNAMIC_NV_PROP, strerror(errno));
702 return;
703 }
704
705 rc = nvbin_sendfile(PERSIST_NVFILE, data_nvfile_path, &data_nvfile_stat);
706 if ( rc != SUCCESS)
707 {
708 ALOGE("nvbin_sendfile failed.\n");
709 return;
710 }
711
712 if (property_set(QRD_DYNAMIC_NV_PROP, "done") < 0)
713 {
714 ALOGE("set %s to done failed(%s).\n",
715 QRD_DYNAMIC_NV_PROP, strerror(errno));
716 return;
717 }
718
719 ALOGI("dynamic nv replace sucessfully!\n");
720
721 }
722
main(int argc,char * argv[])723 int main(int argc, char *argv[])
724 {
725 UNUSED(argc), UNUSED(argv);
726 int rc;
727 int fd_dev, ret_cal;
728 #ifdef WCNSS_QMI
729 int nv_mac_addr = FAILED;
730 struct dev_info mdm_detect_info;
731 int nom = 0;
732 #endif
733
734 setup_wlan_config_file();
735
736 #ifdef WCNSS_QMI
737 /* Call ESOC API to get the number of modems.
738 If the number of modems is not zero, only then proceed
739 with the eap_proxy intialization.*/
740
741 nom = get_system_info(&mdm_detect_info);
742
743 if (nom > 0)
744 ALOGE("Failed to get system info, ret %d", nom);
745
746 if (mdm_detect_info.num_modems == 0) {
747 ALOGE("wcnss_service: No Modem support for this target"
748 " number of modems is %d", mdm_detect_info.num_modems);
749 goto nomodem;
750 }
751
752 ALOGE("wcnss_service: num_modems = %d", mdm_detect_info.num_modems);
753
754 if(!check_modem_compatability(&mdm_detect_info)) {
755 ALOGE("wcnss_service: Target does not have external modem");
756 goto nomodem;
757 }
758
759 /* initialize the DMS client and request the wlan mac address */
760
761 if (SUCCESS == wcnss_init_qmi()) {
762
763 rc = wcnss_qmi_get_wlan_address(wlan_nv_mac_addr);
764
765 if (rc == SUCCESS) {
766 nv_mac_addr = SUCCESS;
767 ALOGE("WLAN MAC Addr:" MAC_ADDRESS_STR,
768 MAC_ADDR_ARRAY(wlan_nv_mac_addr));
769 } else
770 ALOGE("Failed to Get MAC addr from modem");
771
772 wcnss_qmi_deinit();
773 }
774 else
775 ALOGE("Failed to Initialize wcnss QMI Interface");
776
777 nomodem:
778 #endif
779
780 dynamic_nv_replace();
781
782 #ifdef WCNSS_QMI
783 setup_wcnss_parameters(&ret_cal, nv_mac_addr);
784 #else
785 setup_wcnss_parameters(&ret_cal);
786 #endif
787
788 fd_dev = open(WCNSS_DEVICE, O_RDWR);
789 if (fd_dev < 0) {
790 ALOGE("Failed to open wcnss device : %s",
791 strerror(errno));
792 return fd_dev;
793 }
794
795 if (ret_cal != FAILED) {
796 rc = wcnss_write_cal_data(fd_dev);
797 if (rc != SUCCESS)
798 ALOGE("No cal data is written to WCNSS %d", rc);
799 else
800 ALOGE("Cal data is successfully written to WCNSS");
801 }
802
803 setup_wlan_driver_ath_prop();
804
805 rc = wcnss_read_and_store_cal_data(fd_dev);
806 if (rc != SUCCESS)
807 ALOGE("Failed to read and save cal data %d", rc);
808 else
809 ALOGI("Calibration data was successfull written to %s",
810 WCNSS_CAL_FILE);
811
812 close(fd_dev);
813
814 return rc;
815 }
816