xref: /OK3568_Linux_fs/external/rk_pcba_test/echo_pcbatest_server.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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