blob: ac68a3b284ab29176eb3677eb9fa1247579e8ee9 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/* Copyright Statement:
2 *
3 * This software/firmware and related documentation ("MediaTek Software") are
4 * protected under relevant copyright laws. The information contained herein is
5 * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
6 * the prior written permission of MediaTek inc. and/or its licensors, any
7 * reproduction, modification, use or disclosure of MediaTek Software, and
8 * information contained herein, in whole or in part, shall be strictly
9 * prohibited.
10 *
11 * MediaTek Inc. (C) 2016~2017. All rights reserved.
12 *
13 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
14 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
15 * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
16 * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
17 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
19 * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
20 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
21 * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
22 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
23 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
24 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
25 * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
26 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
27 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
28 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
29 * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
30 * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
31 * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
32 *
33 * The following software/firmware and/or related documentation ("MediaTek
34 * Software") have been modified by MediaTek Inc. All revisions are subject to
35 * any receiver's applicable license agreements with MediaTek Inc.
36 */
37
38//- vim: set ts=4 sts=4 sw=4 et: --------------------------------------------
39#include <errno.h>
40#include <unistd.h>
41#include <fcntl.h>
42#include <string.h>
43#include <stdlib.h>
44#include <signal.h>
45#include <sys/time.h>
46#include <sys/resource.h>
47
48#include "boots.h"
49#include "boots_skt.h"
50#include "boots_uart.h"
51#include "boots_eth.h"
52#include "boots_pkt.h"
53#include "boots_stress.h"
54#include "boots_country.h"
55#include "boots_osi.h"
56
57//---------------------------------------------------------------------------
58#define LOG_TAG "boots"
59
60//---------------------------------------------------------------------------
61static boots_if_s boots_if;
62static uint8_t boots_local_exe;
63int boots_loop_timer;
64rssi_set_s rssi_setting;
65
66//---------------------------------------------------------------------------
67static void boots_chk_if(int argc, char **argv)
68{
69 // Please follow the boots_if_e
70 char *c_inf[] = {"None", "stpbt", "hci", "All", "Socket", "UART", "Ethernet",
71 "User", "Tester_UART"};
72 int i = 0;
73#ifdef BOOTS_VERBOSE_MSG
74 BPRINT_D("%s: argc = %d", __func__, argc);
75 for (i = 0; i < argc; i++)
76 BPRINT_D("argv[%d]:%s", i, argv[i]);
77 i = 0;
78#endif
79
80#if 0
81 if (*argv[0] == '-') {
82 if (memcmp(argv[0], "-relay", strlen("-relay"))) {
83 boots_if.clif = BOOTS_CLIF_USER;
84 boots_if.csif = BOOTS_CSIF_SKT;
85 } else if (argc >= 2) {
86 // boots_srv as relayer in PC/NB
87 boots_if.csif = BOOTS_CSIF_UART;
88 if (argc == 2)
89 snprintf(boots_if.cs, sizeof(boots_if.cs), "%s", argv[1]);
90 else if (argc >= 3)
91 snprintf(boots_if.cs, sizeof(boots_if.cs), "%s %s", argv[1], argv[2]);
92 goto exit;
93 }
94 } else if (!memcmp(argv[0], "tty", strlen("tty"))) {
95 boots_if.csif = BOOTS_CSIF_UART;
96 snprintf(boots_if.cs, sizeof(boots_if.cs), "/dev/%s", argv[0]);
97 } else if (!memcmp(argv[0], "eth", strlen("eth"))) {
98 boots_if.csif = BOOTS_CSIF_ETH;
99 memcpy(boots_if.cs, argv[1], strlen(argv[1]));
100 }
101
102 if (argc > 2 && !memcmp(argv[1], "-relay", strlen("-relay"))) {
103 boots_if.clif = BOOTS_CLIF_UART;
104 snprintf(boots_if.cli, sizeof(boots_if.cli), "/dev/%s", argv[2]);
105 } else {
106 boots_if.clif = BOOTS_CLIF_USER;
107 }
108#else
109 while (i < argc) {
110 // check interface for BT side
111 if (!memcmp(argv[i], "tty", strlen("tty"))) {
112 if (i + 1 < argc) {
113 boots_if.csif = BOOTS_CSIF_UART;
114 if (memcmp(argv[i], "/dev/", strlen("/dev/")))
115 snprintf(boots_if.cs, sizeof(boots_if.cs), "/dev/%s", argv[i]);
116 boots_if.cs_speed = strtol(argv[i + 1], NULL, 10);
117 BPRINT_D("cs_speed: %d", boots_if.cs_speed);
118 i += 2;
119 } else {
120 BPRINT_E("Lack a parameter for %s", argv[i]);
121 return;
122 }
123 } else if (!memcmp(argv[i], "eth", strlen("eth"))) {
124 boots_if.csif = BOOTS_CSIF_ETH;
125 long cp_len = strlen(argv[i + 1]) > sizeof(boots_if.cs) ? sizeof(boots_if.cs) : strlen(argv[i + 1]);
126 memcpy(boots_if.cs, argv[i + 1], cp_len);
127 i += 2;
128 } else if (!memcmp(argv[i], "-relay", strlen("-relay"))) {
129 if (boots_if.csif == BOOTS_IF_NONE) {
130 // boots_srv as relayer in PC/NB
131 if (i + 2 < argc && strtol(argv[i + 2], NULL, 10) != 0) {
132 snprintf(boots_if.cs, sizeof(boots_if.cs), "%s %s", argv[i + 1], argv[i + 2]);
133 i += 2;
134 } else if (i + 1 < argc) {
135 snprintf(boots_if.cs, sizeof(boots_if.cs), "%s", argv[i + 1]);
136 i++;
137 } else {
138 BPRINT_E("Lack a parameter for %s", argv[i]);
139 return;
140 }
141 boots_if.csif = BOOTS_CSIF_UART;
142 } else {
143 // boots CLI
144 if (i + 2 < argc && !memcmp(argv[i + 1], "tty", strlen("tty"))
145 && strtol(argv[i + 2], NULL, 10) != 0) {
146 snprintf(boots_if.cli, sizeof(boots_if.cli), "/dev/%s", argv[i + 1]);
147 boots_if.cli_speed = strtol(argv[i + 2], NULL, 10);
148 boots_if.clif = BOOTS_CLIF_UART;
149 i += 2;
150 } else {
151 BPRINT_E("Incorrect argument for %s", argv[i]);
152 return;
153 }
154 }
155 } else if (*argv[i] == '-') {
156 boots_if.clif = BOOTS_CLIF_USER;
157 i++;
158 } else {
159 i++;
160 }
161 }
162
163 if (boots_if.csif == BOOTS_IF_NONE) {
164 boots_if.csif = BOOTS_CSIF_SKT;
165 boots_if.clif = BOOTS_CLIF_USER;
166 }
167#endif
168 BPRINT_D("cs: %s, cs_speed: %d", boots_if.cs, boots_if.cs_speed);
169 BPRINT_I("%s(%d) <-> %s(%d) <-> server", c_inf[boots_if.clif],
170 boots_if.clif, c_inf[boots_if.csif], boots_if.csif);
171}
172
173//---------------------------------------------------------------------------
174static char *boots_chk_btif(char *interface)
175{
176#define BOOTS_SRV_LOCAL "./boots_srv "
177#define BOOTS_SRV "boots_srv "
178#define BOOTS_AND " &"
179
180#define BTPROTO_HCI 1
181
182 int i = 0;
183 static char server[64] = {0};
184
185 if (*interface == '-') { // no assign btif or clif
186 // do auto detect
187 BPRINT_D("%s: DO auto detect", __func__);
188 if (access(boots_btif[0].p, R_OK) == 0) {
189 // STPBT
190 i = 0;
191 boots_if.btif = BOOTS_BTIF_STPBT;
192 } else if ((i = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) != -1) {
193 // HCI
194 BPRINT_D("%s: HCI: %d", __func__, i);
195 close(i);
196 i = 1;
197 boots_if.btif = BOOTS_BTIF_HCI;
198 } else {
199 BPRINT_E("%s: stpbt/HCI are all not exist", __func__);
200 return NULL;
201 }
202 } else {
203 BPRINT_D("%s: btif assigned %s", __func__, interface);
204 while (boots_btif[i].inf) {
205 if (!strcmp(interface, boots_btif[i].n))
206 break;
207 i++;
208 }
209 boots_if.btif = boots_btif[i].inf;
210 if (i + 1 == ARRAY_SIZE(boots_btif)) {
211 BPRINT_E("%s: boots doesn't support \"%s\"", __func__, interface);
212 return NULL;
213 }
214 }
215
216 if (boots_if.clif == BOOTS_IF_NONE && boots_if.csif == BOOTS_CSIF_UART && strlen(boots_if.cs)) {
217 snprintf(server, sizeof(server), boots_local_exe ? BOOTS_SRV_LOCAL "%s %s &" : BOOTS_SRV "%s %s &", boots_if.cs, boots_btif[i].n);
218 } else {
219 snprintf(server, sizeof(server), boots_local_exe ? BOOTS_SRV_LOCAL "%s &" : BOOTS_SRV "%s &", boots_btif[i].n);
220 }
221 BPRINT_D("%s: server: %s", __func__, server);
222 return server;
223}
224
225//---------------------------------------------------------------------------
226static int boots_invoke_boots_srv(char *path)
227{
228 int cont = 0;
229 if (path == NULL) return 0;
230
231 // check boots_srv is running or not
232 if (osi_system("pidof boots_srv > /dev/null") != 0) {
233 if (osi_system(path) == 0) {
234 BPRINT_I("Server(%s) executing...", path);
235 while(access(BOOTS_SRVSK_NAME, F_OK) == -1) {
236 usleep(100 * 1000);
237 cont++;
238 if (cont > 20) {
239 BPRINT_E("access BOOTS_SRVSK_NAME(%s) failed: %s(%d)", BOOTS_SRVSK_NAME, strerror(errno), errno);
240 return 0;
241 }
242 }
243 } else {
244 BPRINT_E("***** WARNING: Please input # %s, if boots_srv isn't running *****",
245 path);
246 }
247 }
248 return 1;
249}
250
251//---------------------------------------------------------------------------
252static int boots_killall_boots_srv(void)
253{
254 int ret = -1;
255
256 ret = osi_system("killall boots_srv > /dev/null");
257 if (ret) {
258 BPRINT_W("*** Please input #killall boots_srv ***");
259 BPRINT_D("%s: kill boots_srv(%d)", __func__, ret);
260 }
261
262 return ret;
263}
264
265//---------------------------------------------------------------------------
266static void boots_sig_handler(int signum)
267{
268 UNUSED(signum);
269 if (BOOTS_STRESS_MEASURE_IN_BOOTS)
270 boots_stress_deinit();
271 exit(0);
272}
273
274//---------------------------------------------------------------------------
275static void boots_tell_socket_end(int fd, struct sockaddr_un *addr)
276{
277 char skend[] = {'s', 'e', 'n', 'd'};
278
279 boots_sk_send(fd, (void *)skend, sizeof(skend), addr, BOOTS_SRVSK_NAME);
280}
281
282static void boots_tell_ethernet_end(int fd, struct sockaddr_in *addr)
283{
284 char skend[] = {'s', 'e', 'n', 'd'};
285 addr->sin_family = AF_INET;
286 addr->sin_port = ETH_UDP_SRV_PORT;
287 addr->sin_addr.s_addr = inet_addr(boots_if.cs);
288 boots_eth_send(fd, (void *)skend, sizeof(skend), addr);
289}
290
291//---------------------------------------------------------------------------
292#define USAGE_DETAILS (1 << 0)
293#define USAGE_DETAILS_MTK (1 << 1)
294static void boots_cmd_usage(uint8_t detail)
295{
296 int i = 0;
297 extern boots_cmds_s commands[];
298
299 printf("Boots - MTK Bluetooth Test Suite ver:%s(rev:%s)\n", VERSION, REV);
300 printf("Modular Commands:\n");
301 for (i = 0; commands[i].cmd; i++) {
302 if (commands[i].hidden == false)
303 printf(" "BLUE"%s"NONE" - %s\n", commands[i].cmd, commands[i].comment);
304 else if (detail & USAGE_DETAILS_MTK)
305 printf(" "BLUE"%s"NONE" - %s\n", commands[i].cmd, commands[i].comment);
306
307 if (detail & USAGE_DETAILS && commands[i].details) {
308 if (commands[i].hidden == false)
309 printf("%s\n", commands[i].details);
310 else if (detail & USAGE_DETAILS_MTK)
311 printf("%s\n", commands[i].details);
312 }
313 }
314 printf("For specfic command details use: ./boots -c <CMD> -h\n");
315}
316
317//---------------------------------------------------------------------------
318static void boots_country_cmd_usage(uint8_t detail)
319{
320 int i = 0;
321 extern boots_country_cmds_s country_commands[];
322
323 printf("Boots - MTK Bluetooth Test Suite ver:%s(rev:%s)\n", VERSION, REV);
324 printf("Power Limit Commands:\n");
325 for (i = 0; country_commands[i].cmd; i++) {
326 if (country_commands[i].hidden == false)
327 printf(" "BLUE"%s"NONE" - %s\n", country_commands[i].cmd, country_commands[i].comment);
328 else if (detail & USAGE_DETAILS_MTK)
329 printf(" "BLUE"%s"NONE" - %s\n", country_commands[i].cmd, country_commands[i].comment);
330
331 if (detail & USAGE_DETAILS && country_commands[i].details) {
332 if (country_commands[i].hidden == false)
333 printf("%s\n", country_commands[i].details);
334 else if (detail & USAGE_DETAILS_MTK)
335 printf("%s\n", country_commands[i].details);
336 }
337 }
338 printf("For specfic command details use: ./boots -c <CMD> -h\n");
339}
340
341//---------------------------------------------------------------------------
342static void boots_help(void)
343{
344 printf("Boots - MTK Bluetooth Test Suite ver:%s(rev:%s)\n", VERSION, REV);
345 printf("Usage:\n");
346 printf(BLUE" boots [BT Interface] <InputMethod/RelayMode> [parameters]\n"NONE);
347 printf(" NOTE: DO NOTE reorder\n");
348 printf(" BT Interface:\n");
349 printf("\tPlease ignore this if not through UART/Ethernet to connect platform(BT)\n");
350 printf("\tttyX Through UART send to BT\n");
351 printf("\t ex: ./boots ttyACM0 115200 ...\n");
352 printf("\tethX Through Ethernet send to BT, need server IP\n");
353 printf("\t ex: ./boots eth0 10.1.1.1 ...\n");
354 printf(" InputMethod: [parameters]\n");
355 printf("\t-f File, ex: ./boots -f test.boots\n");
356 printf("\t-r Raw data, ex: ./boots -r CMD 03 0C 00\n");
357 printf("\t-c Command, for more command information on the usage of everyone command use:\n");
358 printf("\t ./boots -c [detail]\n");
359 printf("\t-relay Through serial port to input\n");
360 printf("\t ex: ./boots ttyACM0 115200 -relay ttyUSB0 115200\n");
361 printf("\t ex: ./boots -relay ttyGS2\n");
362 printf("\t ex: ./boots -relay eth0 10.1.1.1\n");
363 printf(" Others:\n");
364 printf("\tstop Stop service since boots_srv is running in background\n");
365}
366
367//---------------------------------------------------------------------------
368static ssize_t boots_read(int fd, void *buf, size_t buf_size, int inf)
369{
370 ssize_t ret = 0;
371
372 if (!buf || !buf_size || !inf) {
373 BPRINT_E("%s: Invalid argument(buf: %p, buf size: %d, inf: %d)",
374 __func__, buf, (int)buf_size, inf);
375 return -EINVAL;
376 } else if (fd < 0) {
377 BPRINT_E("%s: Bad file descriptor(%d)", __func__, fd);
378 return -EBADFD;
379 }
380
381 if (inf == BOOTS_CSIF_SKT) {
382 ret = boots_sk_recv(fd, buf, buf_size, 0, NULL, NULL);
383 } else if (inf == BOOTS_CSIF_UART || inf == BOOTS_CLIF_UART) {
384 ret = boots_uart_read(fd, buf, buf_size);
385 } else if (inf == BOOTS_CSIF_ETH) {
386 ret = boots_eth_recv(fd, buf, buf_size, 0);
387 } else {
388 BPRINT_E("%s: Incorrect interface(%d)", __func__, inf);
389 }
390 return ret;
391}
392
393//---------------------------------------------------------------------------
394static ssize_t boots_write(int fd, const void *buf, size_t len, int inf)
395{
396 ssize_t ret = 0;
397
398 if (!buf || !len || !inf) {
399 BPRINT_E("%s: Invalid argument(buf: %p, len: %d, inf: %d)", __func__, buf, (int)len, inf);
400 return -EINVAL;
401 } else if (fd < 0) {
402 BPRINT_E("%s: Bad file descriptor(%d)", __func__, fd);
403 return -EBADFD;
404 }
405
406 if (inf == BOOTS_CSIF_SKT) {
407 ret = boots_sk_send(fd, buf, len, NULL, BOOTS_SRVSK_NAME);
408 } else if (inf == BOOTS_CSIF_UART || inf == BOOTS_CLIF_UART) {
409 ret = boots_uart_write(fd, buf, len);
410 } else if (inf == BOOTS_CSIF_ETH) {
411 struct sockaddr_in sockaddr;
412 sockaddr.sin_family = AF_INET;
413 sockaddr.sin_port = ETH_UDP_SRV_PORT;
414 sockaddr.sin_addr.s_addr = inet_addr(boots_if.cs);
415 ret = boots_eth_send(fd, buf, len, &sockaddr);
416 } else {
417 BPRINT_E("%s: Incorrect interface(%d)", __func__, inf);
418 }
419 return ret;
420}
421
422//---------------------------------------------------------------------------
423void boots_chk_local_exe(char *argv)
424{
425 if (argv == NULL) {
426 BPRINT_E("%s: argv should not NULL", __func__);
427 return;
428 }
429
430 if (*argv == '.' && *(argv + 1) == '/') {
431 boots_local_exe = 1;
432 } else {
433 boots_local_exe = 0;
434 }
435}
436
437//---------------------------------------------------------------------------
438int main(int argc, char *argv[])
439{
440 static pkt_list_s *pkt = NULL;
441 static script_set_s sfile = {NULL, 0, 0, 0, 0};
442 static uint8_t buf[HCI_BUF_SIZE] = {0};
443 static int cont = 0;
444 size_t len = 0;
445 ssize_t read_len = 0;
446 int csw_fd = -1;
447 int csr_fd = -1;
448 int cli_uartfd = -1;
449 int type = 0;
450 struct sockaddr_un skaddr_cli;
451 struct sockaddr_un skaddr_srv;
452 socklen_t sklen_cli = {0};
453 socklen_t sklen_srv = {0};
454 struct sockaddr_in ethaddr_cli;
455 struct sockaddr_in ethaddr_srv;
456 fd_set readfs;
457 struct sigaction sigact;
458 struct timeval time_start;
459 struct timeval time_end;
460 uint32_t diff_time;
461 int which = PRIO_PROCESS;
462 id_t pid;
463 int priority = -20;
464 int ret;
465
466 // Register signal handler
467 sigact.sa_handler = boots_sig_handler;
468 sigact.sa_flags = 0;
469 sigemptyset(&sigact.sa_mask);
470 sigaction(SIGINT, &sigact, NULL);
471 sigaction(SIGTERM, &sigact, NULL);
472 sigaction(SIGQUIT, &sigact, NULL);
473 sigaction(SIGKILL, &sigact, NULL);
474
475 // For root permission
476 CHECK_USERID();
477
478 // Local execute or not
479 boots_chk_local_exe(argv[0]);
480
481 if (argc == 2 && !memcmp("-c", argv[1], strlen("-c"))) {
482 // Print commands
483 boots_cmd_usage(0);
484 exit(0);
485 } else if (argc == 2 && !memcmp("-o", argv[1], strlen("-o"))) {
486 // Print commands
487 boots_country_cmd_usage(0);
488 exit(0);
489 } else if (argc == 3 && !memcmp("-c", argv[1], strlen("-c"))) {
490 if (!memcmp("detail", argv[2], strlen("detail"))) {
491 boots_cmd_usage(1);
492 exit(0);
493 } else if (!memcmp("mtk", argv[2], strlen("mtk"))) {
494 boots_cmd_usage(3);
495 exit(0);
496 } else {
497 // do nothing for command without any parameters.
498 }
499 } else if (argc == 2 && !memcmp("stop", argv[1], strlen("stop"))) {
500 boots_killall_boots_srv();
501 return 0;
502 } else if (argc == 3 && !memcmp("-o", argv[1], strlen("-o"))) {
503 if (!memcmp("detail", argv[2], strlen("detail"))) {
504 boots_country_cmd_usage(1);
505 exit(0);
506 } else if (!memcmp("mtk", argv[2], strlen("mtk"))) {
507 boots_country_cmd_usage(3);
508 exit(0);
509 } else {
510 // do nothing for command without any parameters.
511 }
512 } else if (argc < 3) {
513 // Print help
514 boots_help();
515 exit(0);
516 }
517
518 /** country command set, because it's not related controller operation
519 * Only access file
520 */
521 if (!memcmp("-o", argv[1], strlen("-o"))) {
522 boots_country_set_handler(argv + 2, argc - 2);
523 goto exit;
524 }
525
526 // Confirm interface between client/server, upper layer
527 boots_chk_if(argc - 1, &argv[1]);
528
529 /** Communication Interface with boots_srv */
530 if (boots_if.csif == BOOTS_CSIF_SKT) {
531 // Check interface is support or not
532 if (!boots_invoke_boots_srv(boots_chk_btif(argv[1])))
533 exit(1);
534
535 // create socket
536 if (boots_sk_create(&csr_fd, &skaddr_cli, &sklen_cli, BOOTS_CLISK_NAME, 0)) {
537 BPRINT_E("Create socket failed");
538 exit(1);
539 }
540
541 // connect socket
542 if (boots_sk_create(&csw_fd, &skaddr_srv, &sklen_srv, BOOTS_SRVSK_NAME, 1)) {
543 BPRINT_E("Connect socket failed");
544 boots_sk_close(&csr_fd);
545 exit(1);
546 }
547
548 } else if (boots_if.csif == BOOTS_CSIF_UART) {
549 if (boots_if.clif == BOOTS_IF_NONE) {
550 // Maybe last time user use command ask BT into DUT mode
551 boots_killall_boots_srv();
552 sleep(1);
553 // means boots_srv as relayer in PC/NB
554 boots_invoke_boots_srv(boots_chk_btif(argv[1]));
555 exit(1);
556
557 } else {
558 // client/server communication interface
559 csw_fd = boots_uart_init(boots_if.cs, boots_if.cs_speed);
560 if (csw_fd < 0) {
561 BPRINT_E("%s: Open serial port:%s failed(%d)!", __func__, boots_if.cs, csw_fd);
562 exit(1);
563 }
564 csr_fd = csw_fd;
565 }
566
567 } else if (boots_if.csif == BOOTS_CSIF_ETH) {
568 // create socket
569 if (boots_eth_create(&csr_fd, &ethaddr_cli, 0)) {
570 BPRINT_E("Create socket failed");
571 exit(1);
572 }
573 // connect socket
574 if (boots_eth_create(&csw_fd, &ethaddr_srv, 1)) {
575 BPRINT_E("Connect socket failed");
576 boots_eth_close(&csr_fd);
577 exit(1);
578 }
579 } else {
580 BPRINT_E("Unknown communication interface");
581 exit(1);
582 }
583
584 /** Input Interface for boots */
585 if (boots_if.clif == BOOTS_CLIF_UART) {
586 cli_uartfd = boots_uart_init(boots_if.cli, boots_if.cli_speed);
587 if (cli_uartfd < 0) {
588 BPRINT_E("Open serial port:%s failed(%d)!!", boots_if.cli, cli_uartfd);
589 goto exit;
590 }
591 cont = 1;
592
593 } else {
594 if ((type = getopt(argc, argv, "frco")) != -1) {
595 BPRINT_D("optopt: %d, opterr: %d, optind: %d", optopt, opterr, optind);
596 switch (type) {
597 case 'f': /** script file */
598 sfile.script = boots_script_open(*(argv + optind));
599 if (!sfile.script) {
600 goto exit;
601 }
602 break;
603 case 'r': /** raw data */
604 pkt = boots_raw_cmd_handler(argv + optind, argc - optind);
605 break;
606 case 'c': /** command set */
607 pkt = boots_cmd_set_handler(argv + optind, argc - optind);
608 break;
609 #if 0 /** process this in above */
610 case 'o':
611 pkt = boots_country_set_handler(argv + optind, argc - optind);
612 break;
613 #endif
614 default:
615 BPRINT_W("Unknown type: %c", type);
616 break;
617 };
618 if (!pkt && !sfile.script) goto exit;
619 }
620 }
621
622 pid = getpid();
623 ret = setpriority(which, pid, priority);
624 if (ret != 0) {
625 BPRINT_I("setpriority fail: %s(%d)", strerror(errno), errno);
626 }
627
628 /** Process handler */
629 do {
630 int ret = -1;
631 struct timeval timo;
632
633 if (sfile.script) {
634 pkt = boots_script_get(sfile.script);
635 if (pkt == NULL)
636 break; // Could end of file
637 }
638
639 // default timeout
640 if (sfile.timo) {
641 timo.tv_sec = sfile.timo / 1000;
642 timo.tv_usec = (sfile.timo % 1000) * 1000;
643 } else {
644 timo.tv_sec = 3;
645 timo.tv_usec = 0;
646 }
647 if (pkt) {
648 BPRINT_D("s_type: %d", pkt->s_type);
649 switch (pkt->s_type) {
650 case SCRIPT_NONE: // modular commands
651 case SCRIPT_CMD: // hci_cmd script
652 case SCRIPT_STRESS: // stress test script
653 case SCRIPT_LOOPBACK: // loopback test script
654 case SCRIPT_LPTIMER: // loopback test script with timer
655 pkt = boots_pkt_node_pop(pkt, buf, &len);
656 break;
657 case SCRIPT_TX: // combo tool script
658 pkt = boots_pkt_node_pop(pkt, buf, &len);
659 if (len) {
660 // Send command, if input by user or script
661 boots_write(csw_fd, (void *)buf, len, boots_if.csif);
662 boots_pkt_handler(buf, len, NULL);
663 memset(buf, 0, sizeof(buf));
664 len = 0;
665 }
666 continue;
667 case SCRIPT_RX:
668 case SCRIPT_WAITRX:
669 FD_ZERO(&readfs);
670 if (csr_fd >= 0)
671 FD_SET(csr_fd, &readfs);
672 ret = select(csr_fd + 1, &readfs, NULL, NULL, &timo);
673 if (ret > 0) {
674 read_len = boots_read(csr_fd, buf, sizeof(buf), boots_if.csif);
675 if (read_len > 0) {
676 cont = boots_pkt_handler(buf, (size_t)read_len, pkt ? &pkt : NULL);
677 memset(buf, 0, sizeof(buf));
678 read_len = 0;
679 }
680 } else if (ret == 0) {
681 goto exit;
682 }
683 continue;
684 case SCRIPT_TITLE:
685 case SCRIPT_PROC:
686 BPRINT_I("%s", pkt->u_cnt.msg); // Just print msg
687 pkt = boots_pkt_node_pop(pkt, NULL, NULL);
688 continue;
689 case SCRIPT_TIMEOUT:
690 if (pkt->u_cnt.timo) {
691 sfile.timo = pkt->u_cnt.timo;
692 }
693 pkt = boots_pkt_node_pop(pkt, NULL, NULL);
694 continue;
695 case SCRIPT_WAIT:
696 if (pkt->u_cnt.wait) {
697 (void)usleep(pkt->u_cnt.wait * 1000);
698 }
699 pkt = boots_pkt_node_pop(pkt, NULL, NULL);
700 continue;
701 case SCRIPT_USBALT:
702 // TODO
703 continue;
704 case SCRIPT_LOOP:
705 sfile.loop = pkt->u_cnt.loop;
706 if (sfile.script)
707 sfile.loop_pos = ftell(sfile.script);
708 pkt = boots_pkt_node_pop(pkt, NULL, NULL);
709 BPRINT_D("Looping");
710 continue;
711 case SCRIPT_LOOPEND:
712 if (!sfile.loop) {
713 sfile.loop_pos = 0;
714 BPRINT_D("Loop End");
715 } else {
716 if ((--sfile.loop) && sfile.script && sfile.loop_pos >= 0)
717 boots_script_loop(sfile.script, sfile.loop_pos);
718 }
719 pkt = boots_pkt_node_pop(pkt, NULL, NULL);
720 continue;
721 case SCRIPT_RSSI: // Background RSSI scan
722 if (pkt->u_cnt.rssi_s->stop)
723 boots_pkt_cleanup_report_rssi(1);
724 else {
725 boots_pkt_cleanup_report_rssi(0);
726 memcpy(&rssi_setting, pkt->u_cnt.rssi_s, sizeof(rssi_set_s));
727 }
728 buf[0] = SCRIPT_RSSI;
729 memcpy(&buf[1], pkt->u_cnt.rssi_s, sizeof(rssi_set_s));
730 len = sizeof(rssi_set_s) + 1;
731 boots_write(csw_fd, (void *)buf, len, boots_if.csif);
732 memset(buf, 0, sizeof(buf));
733 len = 0;
734 pkt = boots_pkt_node_pop(pkt, NULL, NULL);
735 break;
736 case SCRIPT_END:
737 BPRINT_I("Script End");
738 pkt = boots_pkt_node_pop(pkt, NULL, NULL);
739 boots_script_close(sfile.script);
740 sfile.script = NULL;
741 goto exit;
742 default:
743 break;
744 }
745 }
746
747 if (len) {
748 if (pkt && (pkt->s_type == SCRIPT_STRESS || pkt->s_type == SCRIPT_LOOPBACK || pkt->s_type == SCRIPT_LPTIMER)) {
749 if (BOOTS_STRESS_MEASURE_IN_BOOTS)
750 boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_SEND_CMD_START);
751 }
752
753 // Send command, if input by user or script
754 boots_write(csw_fd, (void *)buf, len, boots_if.csif);
755
756 if (pkt && (pkt->s_type == SCRIPT_STRESS || pkt->s_type == SCRIPT_LOOPBACK || pkt->s_type == SCRIPT_LPTIMER)) {
757 if (BOOTS_STRESS_MEASURE_IN_BOOTS)
758 boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_SEND_CMD_FINISH);
759 if (BOOTS_STRESS_SHOW_ALL_CMD)
760 boots_pkt_handler(buf, len, NULL);
761 if (pkt->s_type == SCRIPT_LPTIMER)
762 gettimeofday(&time_start, NULL);
763 } else
764 boots_pkt_handler(buf, len, NULL);
765 memset(buf, 0, sizeof(buf));
766 len = 0;
767 }
768
769 FD_ZERO(&readfs);
770
771 if (cli_uartfd >= 0)
772 FD_SET(cli_uartfd, &readfs);
773 if (csr_fd >= 0)
774 FD_SET(csr_fd, &readfs);
775
776 ret = select(MAX(cli_uartfd, csr_fd) + 1, &readfs, NULL, NULL, &timo);
777 if (ret > 0) {
778 if (cli_uartfd >= 0 && FD_ISSET(cli_uartfd, &readfs)) {
779 // read from UART(CBT)
780 read_len = boots_read(cli_uartfd, buf, sizeof(buf), boots_if.clif);
781 if (read_len > 0) {
782 // write to platform
783 boots_write(csw_fd, (void *)buf, (size_t)read_len, boots_if.csif);
784 boots_pkt_handler(buf, (size_t)read_len, NULL);
785 memset(buf, 0, sizeof(buf));
786 read_len = 0;
787 }
788 }
789 if (FD_ISSET(csr_fd, &readfs)) {
790 // read from platform
791 read_len = boots_read(csr_fd, buf, sizeof(buf), boots_if.csif);
792
793 if (read_len > 0 && boots_if.clif == BOOTS_CLIF_USER) {
794 cont = boots_pkt_handler(buf, read_len, pkt ? &pkt : NULL);
795 } else if (read_len > 0 && boots_if.clif == BOOTS_CLIF_UART) {
796 // write to UART(CBT)
797 boots_write(cli_uartfd, (void *)buf, read_len, boots_if.clif);
798 boots_pkt_handler(buf, read_len, NULL);
799 }
800
801 if (pkt && pkt->s_type == SCRIPT_STRESS) {
802 if (BOOTS_STRESS_MEASURE_IN_BOOTS)
803 boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_RECEIVE_EVENT_FINISH);
804 } else if (pkt && (pkt->s_type == SCRIPT_LOOPBACK || pkt->s_type == SCRIPT_LPTIMER)) {
805 if (BOOTS_STRESS_MEASURE_IN_BOOTS && !BOOTS_STRESS_MEASURE_LBT_TOTAL_LATENCY)
806 boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_RECEIVE_EVENT_FINISH);
807 if (buf[0] == HCI_EVENT_PKT && read_len == 8) {
808 // should read again (Titan:Why read again but not use it?)
809 boots_read(csr_fd, buf, sizeof(buf), boots_if.csif);
810 } else if (buf[0] == HCI_EVENT_PKT && buf[8] == HCI_ACL_PKT && ((size_t)read_len) == (8 + pkt->len)) {
811 // current loopback test iteration is finished
812 } else if (buf[0] == HCI_ACL_PKT) {
813 // current loopback test iteration is finished
814 } else {
815 BPRINT_E("Receive unknonw type %02X, len=%d(EVENT/ACL is expected)", buf[0], (int)read_len);
816 exit(0);
817 }
818 if (BOOTS_STRESS_MEASURE_IN_BOOTS && BOOTS_STRESS_MEASURE_LBT_TOTAL_LATENCY)
819 boots_stress_record_timestamp(BOOTS_STRESS_TIMESTAMP_RECEIVE_EVENT_FINISH);
820 if (pkt->s_type == SCRIPT_LPTIMER) {
821 gettimeofday(&time_end, NULL);
822 diff_time = (time_end.tv_usec + time_end.tv_sec * 1000000) - (time_start.tv_usec + time_start.tv_sec * 1000000);
823 if (boots_loop_timer > 0 && (unsigned int)boots_loop_timer > (diff_time / 1000))
824 usleep(boots_loop_timer*1000 - diff_time);
825 }
826 }
827 memset(buf, 0, sizeof(buf));
828 read_len = 0;
829 }
830 } else if (ret == 0) {
831 // timeout
832 if (boots_if.clif == BOOTS_CLIF_UART)
833 cont = 1;
834 else
835 cont = 0;
836 } else {
837 BPRINT_D("Unexpect return: %d", ret);
838 }
839 } while (cont || sfile.script);
840
841exit:
842 if (boots_if.csif == BOOTS_CSIF_SKT) {
843 if (csw_fd >= 0)
844 boots_tell_socket_end(csw_fd, &skaddr_srv);
845 (void)usleep(1000);
846 if (csw_fd >= 0)
847 boots_sk_close(&csw_fd);
848 if (csr_fd >= 0)
849 boots_sk_close(&csr_fd);
850 unlink(BOOTS_CLISK_NAME);
851 } else if (boots_if.csif == BOOTS_CSIF_UART) {
852 if (csw_fd >= 0)
853 close(csw_fd);
854 } else if (boots_if.csif == BOOTS_CSIF_ETH) {
855 if (csw_fd >= 0)
856 boots_tell_ethernet_end(csw_fd, &ethaddr_srv);
857 (void)usleep(1000);
858 if (csw_fd >= 0)
859 boots_eth_close(&csw_fd);
860 if (csr_fd >= 0)
861 boots_eth_close(&csr_fd);
862 }
863 if (boots_if.clif == BOOTS_CLIF_UART) {
864 if (cli_uartfd >= 0)
865 close(cli_uartfd);
866 }
867 boots_pkt_list_destroy(pkt);
868 pkt = NULL;
869 boots_script_close(sfile.script);
870 BPRINT_D("Input End");
871 return 0;
872}
873
874//---------------------------------------------------------------------------