1 /*
2 * pcbatest_server.c -- pcba test application
3 *
4 * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
5 * Author: Bin Yang <yangbin@rock-chips.com>
6 * Modified by Panzhenzhuan Wang <randy.wang@rock-chips.com> for rk3036-echo
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 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <dirent.h>
34 #include <linux/watchdog.h>
35
36 #include <sys/ioctl.h>
37 #include <net/if.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <unistd.h>
41
42 #define LOG_TAG "pcbatest_server"
43 #include "common.h"
44 #include "pcbatest_server.h"
45 #include "cJSON/cJSON.h"
46
47 #define PARENT_EXIT 0
48 #define CHILD_EXIT 1
49 #define FORK_FAIL -1
50
51 #ifdef PCBA_PX3SE
52 #define SN_NODE "/sys/devices/2005a000.i2c/i2c-2/2-0054/snread"
53 #else
54 #define SN_NODE ""
55 #endif
56
57 #ifdef PCBA_PX3SE
58 #warning "---------------------define PCBA_PX3SE-----------------------"
59 #elif (defined PCBA_3308)
60 #warning "---------------------define PCBA_3308------------------------"
61 #elif (defined PCBA_3229GVA)
62 #warning "---------------------define PCBA_3229GVA---------------------"
63 #elif (defined PCBA_1808)
64 #warning "---------------------define PCBA_1808------------------------"
65 #elif (defined PCBA_3326)
66 #warning "---------------------define PCBA_3266------------------------"
67 #elif (defined PCBA_PX30)
68 #warning "---------------------define PCBA_PX30------------------------"
69 #elif (defined PCBA_3288)
70 #warning "---------------------define PCBA_3288------------------------"
71 #elif (defined PCBA_3328)
72 #warning "---------------------define PCBA_3328------------------------"
73 #elif (defined PCBA_3399)
74 #warning "---------------------define PCBA_3399------------------------"
75 #elif (defined PCBA_3399PRO)
76 #warning "---------------------define PCBA_3399PRO---------------------"
77 #elif (defined PCBA_1126_1109)
78 #warning "---------------------define PCBA_1126_1109------------------------"
79 #elif (defined PCBA_356X)
80 #warning "---------------------define PCBA_356X---------------------"
81 #elif (defined PCBA_3588)
82 #warning "---------------------define PCBA_3588---------------------"
83 #else
84 #error "====================not define any platform pcba macro here,pls check it======================"
85 #endif
86
sig_child_handle(int sig)87 static void sig_child_handle(int sig)
88 {
89 int status = 0;
90 pid_t pid;
91
92 if (sig == SIGCHLD)
93 while((pid = waitpid(-1, &status, WNOHANG)) > 0);
94 }
95
disable_wdt(void)96 static int disable_wdt(void)
97 {
98 int fd = 0;
99
100 fd = open(DEV_WDT_NAME, O_WRONLY, 0777);
101 if (fd == -1) {
102 log_err ("%s open error\n", DEV_WDT_NAME);
103 } else {
104 write(fd , "V", 1);
105 close(fd);
106 }
107
108 return 0;
109 }
110
run_cmd_to_shell(char * cmd)111 static int run_cmd_to_shell(char* cmd)
112 {
113 int ret = 0;
114 int read_len = 0;
115 FILE* read_fp;
116 char buf[COMMAND_VALUESIZE] = {0};
117
118 read_fp = popen(cmd, "r");
119 if (read_fp != NULL) {
120 read_len = fread(buf, sizeof(char), sizeof(buf), read_fp);
121 if (read_len > 0)
122 ret = 0;
123 else
124 ret = -1;
125 pclose(read_fp);
126 } else {
127 ret = -1;
128 }
129
130 return ret;
131 }
132
run_cmd_to_shell_duplex(char * cmd,char * w_buf,char * r_buf,char * match_str)133 static int run_cmd_to_shell_duplex(char *cmd, char *w_buf, char *r_buf, char *match_str)
134 {
135 int ret = 0, t;
136 int read_len = 0;
137 FILE *fp;
138 char buf[COMMAND_VALUESIZE] = {0};
139 char cmd_msg[COMMAND_VALUESIZE] = {0};
140
141 snprintf(cmd_msg, sizeof(cmd_msg),"%s %s", cmd, w_buf);
142 log_info("========cmd_msg is : %s\n",cmd_msg);
143
144 fp = popen(cmd_msg, "r");
145 if (fp == NULL) {
146 log_err("run_cmd_to_shell_duplex dpopen fail, errno=%d\n", errno);
147 return -1;
148 }
149
150 if(match_str == NULL){
151 read_len = fread(buf, sizeof(char), sizeof(buf), fp);
152 if (read_len <= 0)
153 ret = -1;
154 } else {
155 while (fgets(buf, sizeof(buf) - 1, fp)) {
156 if (strstr(buf, match_str)) {
157 log_info("====================================\n");
158 log_info("strstr(buf, match_str) is : %s\n",buf);
159 strcpy(r_buf, buf);
160 break;
161 } else {
162 puts(buf);
163 }
164 }
165 }
166
167 EXIT:
168 t = pclose(fp);
169 if (WIFEXITED(t))
170 log_info("exit status:%d\n", WEXITSTATUS(t));
171 return ret;
172 }
173
process_is_exists(char * process_name)174 static int process_is_exists(char *process_name)
175 {
176 FILE *fp;
177 char cmd[COMMAND_VALUESIZE] = {0};
178 char buf[COMMAND_VALUESIZE] = {0};
179
180 snprintf(cmd, sizeof(cmd), "ps | grep %s | grep -v grep", process_name);
181 fp = popen(cmd, "r");
182 if (!fp) {
183 log_err("popen ps | grep %s fail\n", process_name);
184 return -1;
185 }
186 while (fgets(buf, sizeof(buf), fp)) {
187 if (strstr(buf, process_name)) {
188 fclose(fp);
189 return 1;
190 }
191 }
192 fclose(fp);
193 return 0;
194 }
195
pcba_test_result_rw(PCBA_SINGLE_PARA * recv_paras,char * w_buf,char * r_buf,bool rw)196 static int pcba_test_result_rw(PCBA_SINGLE_PARA *recv_paras, char *w_buf, char *r_buf, bool rw)
197 {
198 int ret = 0;
199 int fd = -1;
200 char pcbatest_result_filename[COMMAND_VALUESIZE] = {0};
201
202 snprintf(pcbatest_result_filename, sizeof(pcbatest_result_filename),
203 "%s/%s_result", TEST_RESULT_SAVE_PATH,
204 recv_paras[INDEX_TEST_ITEM].valuestr);
205
206 if (rw) {
207 log_info("=================function: %s================\n",__func__);
208 log_info("write result ** pcbatest_result_filename is :%s\n",pcbatest_result_filename);
209 if(w_buf[0]!='\0'){
210 fd = open(pcbatest_result_filename, O_CREAT | O_WRONLY | O_TRUNC, 0777);
211 if (fd < 0) {
212 log_err("open %s fail, errno = %d\n", pcbatest_result_filename, errno);
213 return errno;
214 }
215 assert(strlen(w_buf) < COMMAND_VALUESIZE);
216 int w_len = write(fd, w_buf, strlen(w_buf));
217
218 if (w_len <= 0) {
219 log_err("Write %s fail, errno = %d\n", pcbatest_result_filename, errno);
220 ret = errno;
221 }
222 } else {
223 log_info("w_buf is NUll, do nothing\n");
224 }
225 } else {
226 fd = open(pcbatest_result_filename, O_RDWR, 0777);
227 if (fd < 0) {
228 log_info("can't open %s, errno = %d\n", pcbatest_result_filename, errno);
229 return 1;
230 }
231 int r_len = read(fd, r_buf, COMMAND_VALUESIZE);
232 if (r_len <= 0) {
233 log_err("read %s fail, errno = %d\n", pcbatest_result_filename, errno);
234 ret = errno;
235 }
236
237 log_dbg("%s Result File:%s, Result is: %s\n",
238 __func__, pcbatest_result_filename, r_buf);
239
240 if (strstr(r_buf, TESTITEM_SEND_HEAD) == NULL) {
241 //means this key press info. need to clear file content.
242 close(fd);
243 remove(pcbatest_result_filename);
244 log_info(" XXXXXXXXXX delete file: %s XXXXXXXXXXXXXXX\n", pcbatest_result_filename);
245 return ret;
246 }
247 log_info("**********Read file: %s; Result is: %s**********\n", pcbatest_result_filename, r_buf);
248 }
249 close(fd);
250
251 return ret;
252 }
253
pcba_stop_process(char * process,char * str)254 static int pcba_stop_process(char *process, char *str)
255 {
256 int count = 0;
257
258 while (process_is_exists(process) > 0) {
259 log_info("stop %s... \n", process);
260 system(str);
261 sleep(1);
262 count++;
263 if (count > 3)
264 return -1;
265 }
266 return 0;
267 }
268
pcba_start_process(char * process,char * str)269 static int pcba_start_process(char *process, char *str)
270 {
271 if (process_is_exists(process) > 0) {
272 log_err("process %s already exists \n", process);
273 return -1;
274 }
275 system(str);
276 return 0;
277 }
278
sn_load(char * sn_buff)279 static int sn_load(char* sn_buff)
280 {
281 int i, ret = 0;
282 FILE *fp=NULL;
283 char buff[512];
284 char cmd[COMMAND_VALUESIZE] = {0};
285
286 memset(buff,0,sizeof(buff));
287
288 if(sn_buff == NULL)
289 return -1;
290
291 snprintf(cmd, sizeof(cmd), "cat %s", SN_NODE);
292 if(NULL ==(fp = popen(cmd,"r")))
293 {
294 fprintf(stderr,"execute command failed: %s",strerror(errno));
295 return -1;
296 }
297
298 while (fgets(buff, sizeof(buff), fp)) {
299 char* pstr;
300 pstr = strstr(buff, "sn:");
301 if (pstr) {
302 pstr += strlen("sn:");
303 memcpy(sn_buff, pstr, strlen(buff) - strlen("sn:"));
304 fclose(fp);
305 log_info("xx--------->>>>> SN = %s \n", sn_buff);
306 return 0;
307 }
308 }
309
310 fclose(fp);
311
312 log_info("--------->>>>> SN = %s \n", sn_buff);
313
314 return ret;
315 }
316
enter_pcba_test_mode(char * msg,char * test_flag)317 static int enter_pcba_test_mode(char *msg, char *test_flag)
318 {
319 struct ifreq ifr;
320 char local_mac[18] = {0};
321 char local_sn[32] = {0};
322 int len = 0;
323 char *start = NULL;
324 int sockfd = -1;
325
326 log_info("enter pcba test mode ...\n");
327
328 /*Kill wakeWordAgent process before pcba test*/
329 //new added
330 //system(" kill `ps | grep wakeWordAgent| grep -v grep | awk '{print $1}'`");
331 *test_flag = 1;
332
333 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
334 if (sockfd < 0)
335 log_err("socket creat failed!(UDP)\n");
336 else {
337 strcpy(ifr.ifr_name, "wlan0");
338 while (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
339 usleep(200000); /* 200 ms */
340 }
341 snprintf(local_mac, 18, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
342 (unsigned char)ifr.ifr_hwaddr.sa_data[0],
343 (unsigned char)ifr.ifr_hwaddr.sa_data[1],
344 (unsigned char)ifr.ifr_hwaddr.sa_data[2],
345 (unsigned char)ifr.ifr_hwaddr.sa_data[3],
346 (unsigned char)ifr.ifr_hwaddr.sa_data[4],
347 (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
348 }
349
350 #ifdef PCBA_PX3SE
351 int ret = sn_load(local_sn);
352 #endif
353
354 start = msg;
355 len = strlen(PCBA_TEST_PLATFORM";");
356 memcpy(start, PCBA_TEST_PLATFORM";", len);
357 start += len;
358 len = strlen(local_mac);
359 memcpy(start, local_mac, len);
360
361 #ifdef PCBA_PX3SE
362 if (!ret) {
363 start += len;
364 *start++ = ';';
365 len = strlen(local_sn);
366
367 if (len >= 32) {
368 local_sn[31] = '0';
369 len = 32;
370 }
371 strcat(start, local_sn);
372 }
373 #endif
374
375 return 0;
376 }
377
exit_pcba_test_mode(PCBA_SINGLE_PARA * recv_paras,char * test_flag)378 static int exit_pcba_test_mode(PCBA_SINGLE_PARA *recv_paras, char *test_flag)
379 {
380 DIR *dir = NULL;
381 struct dirent *dir_ptr = NULL;
382 char result_filename[COMMAND_VALUESIZE] = {0};
383 int ret = 0;
384
385 if ((dir = opendir(TEST_RESULT_SAVE_PATH)) == NULL) {
386 log_err("exit test mode opendir fail\n");
387 ret = EXIT_TEST_ERR;
388 }
389 while ((dir_ptr = readdir(dir)) != NULL) {
390 if (strstr(dir_ptr->d_name, "_result")) {
391 snprintf(result_filename, COMMAND_VALUESIZE, "%s/%s",
392 TEST_RESULT_SAVE_PATH, dir_ptr->d_name);
393 remove(result_filename);
394 }
395 }
396 closedir(dir);
397 *test_flag = 0;
398
399 if (*recv_paras[INDEX_MSG].valuestr == '1') {
400 log_info("##########################################################\n");
401 log_info("############# recive exit cmd, will reboot!!! ############\n");
402 log_info("##########################################################\n");
403 }
404
405 #if PCBA_3229GVA
406 /* If the EXIT type command has a "1" message, indicating
407 * that the test is complete, the system will be switched.
408 * If it carries a "0" message, it indicates that the current
409 * test has failed entries.
410 *
411 * Set current system(slot A) unbootable, then reboot.
412 * system in slot B will boot up.
413 */
414 if (*recv_paras[INDEX_MSG].valuestr == '1') {
415 log_info("Set current system unbootable!\n");
416 setSlotAsUnbootable(0);
417 system("busybox reboot");
418 }
419 #endif
420
421 return ret;
422 }
423
pcba_test_item_process(PCBA_SINGLE_PARA * recv_paras)424 static int pcba_test_item_process(PCBA_SINGLE_PARA *recv_paras)
425 {
426 int ret;
427 int fd;
428 char buf[COMMAND_VALUESIZE] = {0};
429 char pcba_test_filename[COMMAND_VALUESIZE] = {0};
430
431 strcpy(pcba_test_filename,recv_paras[INDEX_TEST_ITEM].valuestr);
432
433 chmod(pcba_test_filename, S_IRUSR|S_IWUSR|S_IXUSR);
434
435 ret = run_cmd_to_shell_duplex(pcba_test_filename,
436 recv_paras[INDEX_MSG].valuestr,
437 buf,
438 TESTITEM_SEND_HEAD);
439 if (ret) {
440 log_err("run_cmd_to_shell_duplex fail, ret=%d \n", ret);
441 return TEST_FORK_ERR;
442 }
443
444 log_info("pcba_test_result_rw buf is : %s\n",buf);
445 ret = pcba_test_result_rw(recv_paras, buf, NULL, 1);
446 if (ret)
447 return SAVE_RESULE_ERR;
448
449 return ret;
450 }
451
start_pcba_test_proccess(PCBA_SINGLE_PARA * recv_paras,int * err_code)452 static int start_pcba_test_proccess(PCBA_SINGLE_PARA *recv_paras, int *err_code)
453 {
454 int ret = 0;
455 pid_t pid;
456
457 pid = fork();
458 if (pid < 0) {
459 log_err("fork send_command error\n");
460 return FORK_FAIL;
461 } else if (0 == pid) {
462 if (ret = pcba_test_item_process(recv_paras))
463 log_err("test item process fail, ret=%d\n", ret);
464 *err_code = ret;
465 return CHILD_EXIT;
466 }
467
468 return PARENT_EXIT;
469 }
470
start_pcba_test_preproccess(PCBA_SINGLE_PARA * recv_paras,int test_flag)471 static int start_pcba_test_preproccess(PCBA_SINGLE_PARA *recv_paras, int test_flag)
472 {
473 int ret = 0;
474 char result_filename[COMMAND_VALUESIZE] = {0};
475
476 if (!test_flag) {
477 log_err("not enter pcba test mode \n");
478 ret = TEST_MODE_ERR;
479 }
480
481 snprintf(result_filename, sizeof(result_filename),
482 "%s/%s_result", TEST_RESULT_SAVE_PATH,
483 recv_paras[INDEX_TEST_ITEM].valuestr);
484 if (access(result_filename, F_OK) == 0)
485 return TEST_RESULT_EXIST;
486
487 if (process_is_exists(recv_paras[INDEX_TEST_ITEM].valuestr)) {
488 log_err("start test fail, test item %s already exists\n",
489 recv_paras[INDEX_TEST_ITEM].valuestr);
490 ret = TEST_ITEM_BUSY;
491 }
492
493 return ret;
494 }
495
stop_pcba_test(PCBA_SINGLE_PARA * recv_paras)496 static int stop_pcba_test(PCBA_SINGLE_PARA *recv_paras)
497 {
498 int count = 0;
499 char result_filename[COMMAND_VALUESIZE] = {0};
500 char test_item_process[COMMAND_VALUESIZE] = {0};
501
502 snprintf(result_filename, sizeof(result_filename),
503 "%s/%s_result", TEST_RESULT_SAVE_PATH,
504 recv_paras[INDEX_TEST_ITEM].valuestr);
505 if (access(result_filename, F_OK) == 0)
506 remove(result_filename);
507
508 if (*recv_paras[INDEX_MSG].valuestr == '1') {
509 int fd = -1;
510 char buf[2];
511
512 log_info("stop_pcba_test: msg = %s\n", recv_paras[INDEX_MSG].valuestr);
513
514 memset(result_filename, 0,sizeof(result_filename));
515 snprintf(result_filename, sizeof(result_filename),
516 "%s/stop_result", TEST_RESULT_SAVE_PATH);
517
518 strncpy(buf,recv_paras[INDEX_MSG].valuestr,sizeof(buf));
519
520 fd = open(result_filename, O_CREAT | O_WRONLY | O_TRUNC, 0777);
521 if (fd < 0) {
522 log_err("open %s fail, errno = %d\n", result_filename, errno);
523 //ret = errno;
524 }
525
526 int w_len = write(fd, buf, strlen(buf)); //write to buf '1'
527 if (w_len <= 0) {
528 log_err("Write %s fail, errno = %d\n", result_filename, errno);
529 }
530
531 close(fd);
532 sleep(2);
533 }
534 while (process_is_exists(recv_paras[INDEX_TEST_ITEM].valuestr) > 0) {
535 log_info("kill %s ...\n", recv_paras[INDEX_TEST_ITEM].valuestr);
536 snprintf(test_item_process, sizeof(test_item_process),
537 "busybox killall %s", recv_paras[INDEX_TEST_ITEM].valuestr);
538 run_cmd_to_shell(test_item_process);
539 sleep(1);
540 count++;
541 if (count > 3)
542 return STOP_TEST_ERR;
543 }
544
545 return 0;
546 }
547
query_test_result(PCBA_SINGLE_PARA * recv_paras,char * msg,char * result,int * err_code)548 static int query_test_result(PCBA_SINGLE_PARA *recv_paras, char *msg, char *result, int *err_code)
549 {
550 int ret = 0;
551 int fd;
552 int err = 0;
553 char buf[COMMAND_VALUESIZE];
554
555 *err_code = 0;
556 ret = pcba_test_result_rw(recv_paras, NULL, buf, 0);
557
558 //ret = 1;
559
560 if (ret == 1) {
561 strcpy(result, RESULT_TESTING);
562 return 0;
563 } else if (ret == -1) {
564 log_info("==========function :\t %s==line :\t%d====\n",__func__,__LINE__);
565 return QUERY_RESULT_ERR;
566 }
567 ret = sscanf(buf, TESTITEM_SEND_PARSE, msg, result, &err);
568 log_info("@@@ buf :%s. ret = %d @@@\n", buf, ret);
569 log_info("@@@ msg :%s @@@\n", msg);
570 log_info("@@@ result :%s @@@\n", result);
571 log_info("@@@ err :%d @@@\n", err);
572 log_info("***************ret = : %d\n", ret);
573 assert(strlen(buf) < COMMAND_VALUESIZE);
574 assert(strlen(msg) < COMMAND_VALUESIZE);
575 if (ret != 3) {
576 ret = sscanf(buf, TESTITEM_SEND_PARSE_NOMSG, result, &err);
577 if (ret != 2) {
578 log_err("pcbatest result query fail, msg:%s, result:%s, err_code:%d, ret=%d\n",
579 msg, result, err, ret);
580
581 return QUERY_RESULT_ERR;
582 }
583 }
584 *err_code = err;
585
586 return 0;
587 }
588
tcp_command_check(PCBA_COMMAND_FORMAT index,char * str)589 static int tcp_command_check(PCBA_COMMAND_FORMAT index, char *str)
590 {
591 int num = 0;
592 char pcba_test_filename[COMMAND_VALUESIZE] = {0};
593 struct stat file_stat;
594
595 switch (index) {
596 case INDEX_TYPE:
597 if (strcmp(str, RECV_TYPE_NAME)) {
598 log_err("not found type (%s) is error type\n", str);
599 return CMD_TYPE_ERR;
600 }
601 break;
602
603 case INDEX_TEST_ITEM:
604 snprintf(pcba_test_filename, sizeof(pcba_test_filename),
605 "%s%s", PCBA_TEST_PATH, str);
606
607
608 if (access(pcba_test_filename, F_OK)) {
609 log_err("not found test item(%s), test not support!\n", pcba_test_filename);
610 return TEST_ITEM_ERR;
611 }
612 break;
613
614 case INDEX_CMD:
615 for (num = 0; num < RECV_CMD_NUM; num++ ) {
616 if (!strcmp(str, recv_cmd_type[num].name))
617 break;
618 }
619 if (num == RECV_CMD_NUM) {
620 log_err("not found command (%s) is error command.\n", str);
621 return CMD_ERR;
622 }
623 break;
624
625 case INDEX_MSG:
626 break;
627
628 default:
629 return RECV_FORMAT_ERR;
630 }
631
632 return CMD_CHK_OK;
633 }
634
tcp_command_fill(PCBA_COMMAND_PARA * cmd_paras,char * status,char * msg,char * result,int err_code)635 static void tcp_command_fill(PCBA_COMMAND_PARA *cmd_paras, char *status, char *msg,
636 char *result, int err_code)
637 {
638 int num = 0;
639 char str_err_code[20];
640 bool *opt;
641 bool send_para_optional[SEND_COMMAND_PARANUM];
642 PCBA_SINGLE_PARA *recv_paras = cmd_paras->recv_paras;
643 PCBA_SINGLE_PARA *send_paras = cmd_paras->send_paras;
644
645 for (num = 0; num < SEND_COMMAND_PARANUM; num++)
646 send_para_optional[num] = false;
647
648 if ((!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[ENTER_CMD].name)) || \
649 (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[EXIT_CMD].name))) {
650 send_paras[INDEX_TEST_ITEM].opt = true;
651 send_paras[INDEX_RESULT].opt = true;
652 } else if ((!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[START_CMD].name)) || \
653 (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[STOP_CMD].name))) {
654 send_paras[INDEX_RESULT].opt = true;
655 }
656 if (!strcmp(status, NAK_STA))
657 send_paras[INDEX_RESULT].opt = true;
658
659 if ((!send_paras[INDEX_TYPE].opt) && send_paras[INDEX_RES].name)
660 strcpy(send_paras[INDEX_TYPE].valuestr, send_paras[INDEX_RES].name);
661
662 if ((!send_paras[INDEX_TEST_ITEM].opt) && recv_paras[INDEX_TEST_ITEM].valuestr)
663 strcpy(send_paras[INDEX_TEST_ITEM].valuestr, recv_paras[INDEX_TEST_ITEM].valuestr);
664
665 if ((!send_paras[INDEX_RES].opt) && recv_paras[INDEX_CMD].valuestr)
666 strcpy(send_paras[INDEX_RES].valuestr, recv_paras[INDEX_CMD].valuestr);
667
668 if ((!send_paras[INDEX_MSG].opt) && msg)
669 strcpy(send_paras[INDEX_MSG].valuestr, msg);
670
671 if ((!send_paras[INDEX_STATUS].opt) && status)
672 strcpy(send_paras[INDEX_STATUS].valuestr, status);
673
674 if ((!send_paras[INDEX_RESULT].opt) && result)
675 strcpy(send_paras[INDEX_RESULT].valuestr, result);
676
677 if (!send_paras[INDEX_ERRCODE].opt) {
678 snprintf(str_err_code, sizeof(str_err_code), "%d", err_code);
679 strcpy(send_paras[INDEX_ERRCODE].valuestr, str_err_code);
680 }
681 }
682
tcp_command_creat(char * send_buf,int send_size,PCBA_SINGLE_PARA * send_paras)683 static int tcp_command_creat(char *send_buf, int send_size, PCBA_SINGLE_PARA *send_paras)
684 {
685 int ret = 0;
686 int num = 0;
687 char * out;
688 cJSON *sendJSON;
689
690 sendJSON = cJSON_CreateObject();
691 if (sendJSON == NULL) {
692 log_err("cJSON_CreateObject error (%s)\n", cJSON_GetErrorPtr());
693 return SEND_FORMAT_ERR;
694 }
695
696 for(num = 0; num < SEND_COMMAND_PARANUM; num++) {
697 if(send_paras[num].opt)
698 continue;
699 cJSON_AddStringToObject(sendJSON, send_paras[num].name, send_paras[num].valuestr);
700 }
701 out = cJSON_Print(sendJSON);
702 if (NULL == out) {
703 log_err("send command cJSON_Print error\n");
704 cJSON_Delete(sendJSON);
705 return SEND_FORMAT_ERR;
706 }
707
708 if (strlen(out) > send_size) {
709 log_err("send command size is %d exceed %d \n", strlen(out), send_size);
710 ret = SEND_FORMAT_ERR;
711 goto EXIT;
712 }
713
714 strcpy(send_buf, out);
715
716 EXIT:
717 cJSON_Delete(sendJSON);
718 free(out);
719
720 return ret;
721 }
722
tcp_command_send(int stock_fd,PCBA_COMMAND_PARA * cmd_paras,char * status,char * msg,char * result,int err_code)723 static int tcp_command_send(int stock_fd, PCBA_COMMAND_PARA *cmd_paras, char *status,
724 char *msg, char *result, int err_code)
725 {
726 int ret = 0;
727 int send_num = 0;
728 char send_buf[SEND_BUFFER_SIZE];
729
730 tcp_command_fill(cmd_paras, status, msg, result, err_code);
731 ret = tcp_command_creat(send_buf, sizeof(send_buf), cmd_paras->send_paras);
732 if (ret) {
733 log_err("send command creat fail, ret=%d\n", ret);
734 return ret;
735 }
736
737 send_num = send(stock_fd, send_buf, sizeof(send_buf), 0);
738 log_info("send_buf is :%s \n",send_buf);
739 if (send_num < 0) {
740 log_err("command tcp send fail, send_num=%d\n", send_num);
741 return TCP_SEND_ERR;
742 }
743
744 return 0;
745 }
746
tcp_command_para_init(PCBA_COMMAND_PARA * cmd_paras)747 static void tcp_command_para_init(PCBA_COMMAND_PARA *cmd_paras)
748 {
749 int num = 0;
750
751 memset(cmd_paras, 0, sizeof(PCBA_COMMAND_PARA));
752 for (num = 0; num < RECV_COMMAND_PARANUM; num++) {
753 strcpy(cmd_paras->recv_paras[num].name, recv_cmd_target[num].name);
754 cmd_paras->recv_paras[num].opt = recv_cmd_target[num].opt;
755 }
756 for (num = 0; num < SEND_COMMAND_PARANUM; num++)
757 strcpy(cmd_paras->send_paras[num].name, send_cmd_target[num].name);
758 }
759
tcp_command_parse(char * recv_buf,PCBA_SINGLE_PARA * recv_paras)760 static int tcp_command_parse(char *recv_buf, PCBA_SINGLE_PARA *recv_paras)
761 {
762 int num = 0;
763 int ret = 0;
764 int err_code = 0;
765 cJSON *recvJSON;
766 cJSON *sub_JSON;
767
768 recvJSON = cJSON_Parse(recv_buf);
769 if (recvJSON == NULL) {
770 log_err("command JSON parse error (%s)\n", cJSON_GetErrorPtr());
771 return RECV_FORMAT_ERR;
772 } else {
773 for (num = 0; num < RECV_COMMAND_PARANUM; num++) {
774 sub_JSON = cJSON_GetObjectItem(recvJSON , recv_paras[num].name);
775 if (sub_JSON) {
776 if ((sub_JSON->type != cJSON_String) || (sub_JSON->valuestring == NULL)) {
777 log_err("parse json type error(%d) or null string \n", sub_JSON->type);
778 ret = RECV_FORMAT_ERR;
779 goto ERR_EXIT;
780 }
781 if (strlen(sub_JSON->valuestring) > sizeof(recv_paras[num].valuestr)) {
782 log_err("recv string length is %d exceed %d \n",
783 strlen(sub_JSON->valuestring),
784 sizeof(recv_paras[num].valuestr));
785 ret = CMD_OVERLONG;
786 goto ERR_EXIT;
787 }
788 strcpy(recv_paras[num].valuestr, sub_JSON->valuestring);
789 if (!err_code) {
790 err_code = tcp_command_check(num, sub_JSON->valuestring);
791 if (err_code) {
792 ret = err_code;
793 log_err("check command %s error\n", recv_paras[num].name);
794 }
795 }
796 } else if (recv_paras[num].opt == false) {
797 log_err("not receive (%s)\n", recv_paras[num].name);
798 ret = RECV_FORMAT_ERR;
799 goto ERR_EXIT;
800 }
801 }
802 }
803
804 ERR_EXIT:
805 cJSON_Delete(recvJSON);
806
807 return ret;
808 }
809
tcp_command_process(int stock_fd,int err_code,PCBA_COMMAND_PARA * cmd_paras)810 static int tcp_command_process(int stock_fd, int err_code, PCBA_COMMAND_PARA *cmd_paras)
811 {
812 int ret = -1;
813 int fork_status = PARENT_EXIT;
814 int item_busy_or_result_exist = 0;
815 static char test_flag = 0;
816 char status[COMMAND_VALUESIZE] = NAK_STA;
817 char msg[COMMAND_VALUESIZE] = {0};
818 char result[COMMAND_VALUESIZE] = RESULT_TESTING;
819 PCBA_SINGLE_PARA *recv_paras = cmd_paras->recv_paras;
820
821 log_info("recv_paras[INDEX_TEST_ITEM].valuestr is :%s---------\n",recv_paras[INDEX_TEST_ITEM].valuestr);
822 if (err_code)
823 goto SEND_CMD;
824
825 if (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[ENTER_CMD].name)) {
826 err_code = enter_pcba_test_mode(msg, &test_flag);
827 } else if (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[EXIT_CMD].name)) {
828 usleep(2000); //sleep 2 ms to let PC have time to read result
829 err_code = exit_pcba_test_mode(recv_paras, &test_flag);
830 } else if (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[START_CMD].name) ||
831 !strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[CAPTURE_CMD].name)) {
832 log_info("[dragon] %s \n", recv_paras[INDEX_CMD].valuestr);
833 err_code = start_pcba_test_preproccess(recv_paras, test_flag);
834 if ((!err_code) && !strcmp(recv_paras[INDEX_TEST_ITEM].valuestr, STORAGE_TESTITEM)) {
835 fork_status = start_pcba_test_proccess(recv_paras, &err_code);
836 if (fork_status != CHILD_EXIT)
837 goto EXIT;
838 if (!err_code) {
839 ret = query_test_result(recv_paras, msg, result, &err_code);
840 if (ret)
841 err_code = ret;
842 }
843 } else if (err_code == TEST_ITEM_BUSY) {
844 item_busy_or_result_exist = 1;
845 err_code = 0;
846 strcpy(result, RESULT_TESTING);
847 } else if (err_code == TEST_RESULT_EXIST) {
848 item_busy_or_result_exist = 1;
849 err_code = 0;
850 }
851 } else if (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[STOP_CMD].name)) {
852 err_code = stop_pcba_test(recv_paras);
853 } else if (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[QUERY_CMD].name)) {
854 if (ret = query_test_result(recv_paras, msg, result, &err_code))
855 err_code = ret;
856 } else {
857 err_code = CMD_ERR;
858 }
859
860 SEND_CMD:
861 if (err_code & ret)
862 strcpy(status, NAK_STA);
863 else
864 strcpy(status, ACK_STA);
865
866 ret = tcp_command_send(stock_fd, cmd_paras, status, msg, result, err_code);
867 if (ret) {
868 log_err("command send fail, err=%d\n", ret);
869 goto EXIT;
870 }
871 if (err_code) {
872 log_err("command process fail, err_code=%d\n", err_code);
873 goto EXIT;
874 }
875
876 if (!item_busy_or_result_exist &&
877 (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[START_CMD].name) ||
878 !strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[CAPTURE_CMD].name)) &&
879 strcmp(recv_paras[INDEX_TEST_ITEM].valuestr, STORAGE_TESTITEM)) {
880
881 if (!strcmp(recv_paras[INDEX_CMD].valuestr, recv_cmd_type[CAPTURE_CMD].name))
882 log_info("[dragon] camera capture cmd run.....\n" , recv_paras[INDEX_CMD].valuestr);
883
884 fork_status = start_pcba_test_proccess(recv_paras, &err_code);
885 }
886
887 EXIT:
888
889 return fork_status;
890 }
891
tcp_client_process(int stock_fd)892 static void tcp_client_process(int stock_fd)
893 {
894 PCBA_COMMAND_PARA cmd_paras_set;
895 PCBA_COMMAND_PARA *cmd_paras = &cmd_paras_set;
896 int recv_num = 0;
897 int parse_ret = 0;
898 int proc_ret = 0;
899 char recv_buf[RECV_BUFFER_SIZE] = {0};
900
901 while(1) {
902 log_info("waiting for client...\n");
903 recv_num = recv(stock_fd, recv_buf, sizeof(recv_buf), 0);
904 log_info("recv_buf is :%s \n",recv_buf);
905 if (recv_num <= 0) {
906 log_err("recv error:%s. goto exit\n", strerror(errno));
907 goto ERR_EXIT;
908 //goto EXIT; //chad.ma modified, recv_num < 0 means host disconnect socket
909 //here we exit normal.
910 }
911 recv_buf[recv_num]='\0';
912
913 tcp_command_para_init(cmd_paras);
914
915 parse_ret = tcp_command_parse(recv_buf, cmd_paras->recv_paras);
916 if (parse_ret == RECV_FORMAT_ERR)
917 continue;
918
919 proc_ret = tcp_command_process(stock_fd, parse_ret, cmd_paras);
920 if (proc_ret == FORK_FAIL){
921 goto ERR_EXIT;
922 }
923
924 else if (proc_ret == CHILD_EXIT)
925 goto EXIT;
926 }
927
928 //free(cmd_paras);
929 ERR_EXIT:
930 close(stock_fd);
931 log_info("-------- exit pcbatest server--------\n");
932 exit(-1);
933 EXIT:
934 //free(cmd_paras);
935 log_info("-------- quit pcbatest server--------\n");
936 exit(0);
937 }
938
init_tcp(void)939 static int init_tcp(void)
940 {
941 int val = 1;
942 int server_sockfd;
943 struct sockaddr_in server_addr;
944 int ret;
945
946 /* create a socket */
947 server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
948 if (server_sockfd < 0) {
949 log_err("socket error:%s\n", strerror(errno));
950 return -1;
951 }
952
953 ret = setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int));
954 if (ret == -1) {
955 log_err("setsockopt error:%s\n", strerror(errno));
956 return -1;
957 }
958
959 /* initialize server address */
960 bzero(&server_addr, sizeof(server_addr));
961 server_addr.sin_family = AF_INET;
962 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
963 server_addr.sin_port = htons(SOURCE_PORT);
964
965 /* bind with the local file */
966 ret = bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
967 if (ret) {
968 log_err("bind error:%s\n", strerror(errno));
969 close(server_sockfd);
970 return -1;
971 }
972
973 /* listen */
974 ret = listen(server_sockfd, TCP_QUEUE_LINE);
975 if (ret) {
976 log_err("listen error:%s\n", strerror(errno));
977 close(server_sockfd);
978 return -1;
979 }
980 log_info("tcp server is ready ... \n");
981
982 return server_sockfd;
983 }
984
main(int argc,char ** argv)985 int main(int argc, char **argv)
986 {
987 int server_sockfd;
988 int client_sockfd;
989 struct sockaddr_in client_addr;
990 socklen_t client_addr_len = sizeof(client_addr);
991 pid_t pid;
992
993 signal(SIGCHLD, sig_child_handle);
994
995 server_sockfd = init_tcp();
996 if (server_sockfd < 0)
997 {
998 log_err("tcp server init fail\n");
999 return -1;
1000 }
1001
1002 log_info("*****************************************\n");
1003 log_info("*** pcba test start ***\n");
1004 log_info("*** Rockchip.Co.Ld. ***\n");
1005 log_info("*****************************************\n");
1006 log_info("pcba test version: v%s\n", PCBA_VERSION);
1007 log_info("pcba test git version: %s\n", BUILD_LOG_VERSION);
1008 log_info("pcba test build date: %s\n", BUILD_DATE);
1009
1010 while(1) {
1011 //{
1012 /* accept a connection */
1013 client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
1014 if (client_sockfd < 0) {
1015 log_err("accept error:%s\n", strerror(errno));
1016 close(server_sockfd);
1017 return -1;
1018 }
1019
1020 log_info("accept a new client, ip:%s, port:%d\n",
1021 inet_ntoa(client_addr.sin_addr),
1022 ntohs(client_addr.sin_port));
1023
1024 pid = fork();
1025 if (pid < 0) {
1026 log_err("fork tcp_client_process error\n");
1027 close(server_sockfd);
1028 return -1;
1029 } else if (0 == pid) {
1030 close(server_sockfd);
1031 tcp_client_process(client_sockfd);
1032 } else if (pid > 0) {
1033 close(client_sockfd);
1034 }
1035 }
1036 close(server_sockfd);
1037
1038 #if 0
1039 int status;
1040 waitpid(pid, &status, 0);
1041 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
1042 log_err("Error in (Status %d)\n", WEXITSTATUS(status));
1043 return -1;
1044 }
1045 #endif
1046 log_info("======Will exit pcba test server & end test ======\n");
1047 return 0;
1048 }
1049