blob: 07128742fcc414ad53bbc17aee637c81a3fb8fa0 [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 <unistd.h>
40#include <fcntl.h>
41#include <errno.h>
42#include <unistd.h>
43
44#include "boots_pkt.h"
45#include "boots_stress.h"
46
47//---------------------------------------------------------------------------
48#define LOG_TAG "boots_pkt"
49
50#define HCE_INQUIRY_COMPLETE 0x01
51#define HCE_INQUIRY_RESULT 0x02
52#define HCE_CONNECTION_COMPLETE 0x03
53#define HCE_COMMAND_COMPLETE 0x0E
54#define HCE_INQUIRY_RESULT_WITH_RSSI 0x22
55#define HCE_EXT_INQUIRY_RESULT 0x2F
56
57#define DEFAULT_WIFI_CFG "/vendor/firmware/wifi.cfg"
58#define E2P_MODE "EfuseBufferModeCal"
59
60//---------------------------------------------------------------------------
61typedef struct {
62 uint8_t pt; // Packet Type
63 uint16_t len; // Data Length
64} packet_info_s;
65
66typedef enum {
67 WR_FLAG_NO,
68 WR_FLAG_READ,
69 WR_FLAG_WRITE
70} wr_flag_e;
71
72typedef struct {
73 uint32_t addr;
74 uint32_t value;
75 wr_flag_e wr_flag;
76} efuse_reg_wr_s;
77
78static const packet_info_s tx_pi[] = { // TX packet info
79 {0x00, 0x0000}, {0x01, 0x0000}, {0x02, 0x0000}, {0x03, 0x0011},
80 {0x04, 0x001B}, {0x05, 0x000A}, {0x06, 0x0014}, {0x07, 0x001E},
81 {0x08, 0x0013}, {0x09, 0x000A}, {0x0A, 0x0079}, {0x0B, 0x00B7},
82 {0x0E, 0x00E0}, {0x0F, 0x0153}, {0x17, 0x001E}, {0x1C, 0x0078},
83 {0x1D, 0x00B4}, {0x24, 0x0036}, {0x28, 0x0053}, {0x2A, 0x016F},
84 {0x2B, 0x0228}, {0x2E, 0x02A7}, {0x2F, 0x03FD}, {0x36, 0x003C},
85 {0x37, 0x005A}, {0x3C, 0x0168}, {0x3D, 0x021C}};
86
87static const packet_info_s rx_pi[] = { // RX packet info
88 {0x03, 0x0011}, {0x04, 0x001B}, {0x0A, 0x0079}, {0x0B, 0x00B7},
89 {0x0E, 0x00E0}, {0x0F, 0x0153}, {0x24, 0x0036}, {0x28, 0x0053},
90 {0x2A, 0x016F}, {0x2B, 0x0053}, {0x2E, 0x02A7}, {0x2F, 0x03FD}};
91
92static efuse_reg_wr_s efuse_reg_wr = {0, 0, WR_FLAG_NO};
93static int rssi_channels[79];
94static int rssi_count = 0;
95
96extern int boots_loop_timer;
97extern rssi_set_s rssi_setting;
98
99//---------------------------------------------------------------------------
100static void boots_write_stpbtfwlog(char *buf);
101
102//---------------------------------------------------------------------------
103void boots_pkt_cleanup_report_rssi(uint8_t stop)
104{
105 int i = 0;
106
107 if ((rssi_setting.report == true) && (rssi_count != 0) && (stop == 1)) {
108 BPRINT_I_RAW("\nPackage count: %d, RSSI: \n", rssi_count);
109 for (i = 0; i < 79 ; i++) {
110 rssi_channels[i] = rssi_channels[i] / rssi_count;
111 if (i >= rssi_setting.ch_start && i <= rssi_setting.ch_end) {
112 BPRINT_I_RAW("% 4d ", rssi_channels[i]);
113 } else {
114 BPRINT_I_RAW(" ");
115 }
116 if ((i + 1) % 10 == 0 || i == 78) {
117 BPRINT_I_RAW("\n");
118 }
119 }
120 }
121 rssi_count = 0;
122 memset(rssi_channels, 0x00, sizeof(rssi_channels));
123 memset(&rssi_setting, 0x00, sizeof(rssi_set_s));
124}
125
126//---------------------------------------------------------------------------
127pkt_list_s *boots_pkt_node_push(uint8_t s_type, uint8_t p_type, void *content,
128 size_t len, pkt_list_s *front, pkt_list_s *head)
129{
130 // Create node
131 pkt_list_s *node = (pkt_list_s *)malloc(sizeof(pkt_list_s));
132
133 if (!node) {
134 BPRINT_D("%s: List allocate fail", __func__);
135 return NULL;
136 }
137
138 node->s_type = s_type;
139 switch (s_type) {
140 case SCRIPT_NONE:
141 case SCRIPT_TX:
142 case SCRIPT_RX:
143 case SCRIPT_WAITRX:
144 case SCRIPT_CMD:
145 case SCRIPT_STRESS:
146 case SCRIPT_LOOPBACK:
147 case SCRIPT_LPTIMER:
148 node->p_type = p_type;
149 if (len > 0)
150 node->u_cnt.data = (uint8_t *)malloc(len);
151 if (content && node->u_cnt.data) {
152 memcpy(node->u_cnt.data, (uint8_t *)content, len);
153 node->len = len;
154 }
155 break;
156 case SCRIPT_TITLE:
157 case SCRIPT_PROC:
158 if (len > 0)
159 node->u_cnt.msg = (char *)malloc(len);
160 if (content && node->u_cnt.msg) {
161 memcpy(node->u_cnt.msg, (char *)content, len);
162 node->len = len;
163 }
164 break;
165 case SCRIPT_RSSI:
166 if (len > 0)
167 node->u_cnt.rssi_s = (rssi_set_s *)malloc(len);
168 if (content && node->u_cnt.rssi_s) {
169 memcpy(node->u_cnt.rssi_s, content, len);
170 node->len = len;
171 }
172 break;
173 case SCRIPT_LOOP:
174 if (content)
175 node->u_cnt.loop = *((int *)content);
176 break;
177 case SCRIPT_TIMEOUT:
178 if (content)
179 node->u_cnt.timo = *((int *)content);
180 break;
181 case SCRIPT_WAIT:
182 if (content)
183 node->u_cnt.wait = *((int *)content);
184 break;
185 case SCRIPT_USBALT:
186 if (content)
187 node->u_cnt.usbalt = *((int *)content);
188 break;
189 case SCRIPT_LOOPEND:
190 case SCRIPT_END:
191 break;
192 default:
193 BPRINT_W("Incorrect Script Type: %d", s_type);
194 break;
195 }
196 if (front)
197 front->next = node;
198 node->next = head ? head : node;
199
200 // return node point
201 return node;
202}
203
204//---------------------------------------------------------------------------
205pkt_list_s *boots_pkt_node_pop(pkt_list_s *list, uint8_t *buf, size_t *len)
206{
207 pkt_list_s *tmp = NULL;
208
209 if (!list) return NULL;
210 //BPRINT_D("%s node: %p, next: %p", __func__, list, list->next);
211
212 if (buf && len) {
213 memcpy(buf, list->u_cnt.data, list->len);
214 *len = list->len;
215 }
216
217 // Remove this node from head
218 if (list->next == list) {
219 tmp = NULL;
220 } else {
221 pkt_list_s *tail = NULL;
222
223 tmp = list->next;
224 // round circle
225 tail = tmp;
226 while (tail->next != list) {
227 tail = tail->next;
228 }
229 tail->next = tmp;
230 }
231
232 switch (list->s_type) {
233 case SCRIPT_NONE:
234 case SCRIPT_TX:
235 case SCRIPT_RX:
236 case SCRIPT_WAITRX:
237 case SCRIPT_CMD:
238 free(list->u_cnt.data);
239 break;
240 case SCRIPT_TITLE:
241 case SCRIPT_PROC:
242 free(list->u_cnt.msg);
243 break;
244 case SCRIPT_STRESS:
245 case SCRIPT_LOOPBACK:
246 case SCRIPT_LPTIMER:
247 // return list directly, result in infinite loop.
248 return list;
249 case SCRIPT_RSSI:
250 free(list->u_cnt.rssi_s);
251 break;
252 default:
253 break;
254 }
255 free(list);
256
257 return tmp;
258}
259
260//---------------------------------------------------------------------------
261void boots_pkt_list_destroy(pkt_list_s *list)
262{
263 pkt_list_s *cur = list;
264 pkt_list_s *next = NULL;
265
266 if (!list) return;
267
268 do {
269 if (next) cur = next;
270 next = cur->next;
271 //BPRINT_D("%s cur: %p, next: %p", __func__, cur, next);
272 switch (cur->s_type) {
273 case SCRIPT_NONE:
274 case SCRIPT_TX:
275 case SCRIPT_RX:
276 case SCRIPT_WAITRX:
277 case SCRIPT_CMD:
278 free(cur->u_cnt.data);
279 break;
280 case SCRIPT_TITLE:
281 case SCRIPT_PROC:
282 free(cur->u_cnt.msg);
283 break;
284 default:
285 break;
286 }
287 free(cur);
288 } while (next != list && next != NULL);
289}
290
291//---------------------------------------------------------------------------
292size_t boots_pkt_list_amount(pkt_list_s *list)
293{
294 size_t amount = 1;
295 pkt_list_s *tmp = list;
296
297 if (!list) return 0;
298
299 while (tmp->next != list) {
300 amount++;
301 tmp = tmp->next;
302 }
303 return amount;
304}
305
306//---------------------------------------------------------------------------
307static pkt_list_s *boots_efuse_write(pkt_list_s *list, uint8_t *buf)
308{
309 pkt_list_s * pkt = NULL;
310 uint8_t efuse[] = {0x01, 0x6F, 0xFC, 0x18,
311 0x01, 0x0D, 0x14, 0x00, 0x01, 0x01,
312 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00};
317 size_t len = 0;
318 uint16_t addr = 0;
319
320 boots_pkt_node_pop(list, efuse, &len);
321 if (len != sizeof(efuse)) {
322 BPRINT_E("Error! %d != %d", (int)len, (int)sizeof(efuse));
323 }
324
325 addr = efuse_reg_wr.addr / 16 * 4;
326 efuse[10] = addr & 0xFF;
327 efuse[11] = (addr & 0xFF00) >> 8;
328 memcpy(&efuse[12], &buf[2], 4);
329 memcpy(&efuse[16], &buf[8], 4);
330 memcpy(&efuse[20], &buf[14], 4);
331 memcpy(&efuse[24], &buf[20], 4);
332
333 memcpy(&efuse[12 + efuse_reg_wr.addr % 16], &efuse_reg_wr.value, 1);
334
335 pkt = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, efuse, sizeof(efuse),
336 NULL, NULL);
337
338 return pkt;
339}
340
341//---------------------------------------------------------------------------
342ssize_t boots_file_wr(uint8_t *buf, ssize_t *len)
343{
344 int fd = 0;
345 uint32_t addr = 0;
346 uint8_t value = 0;
347 uint8_t wr = 0;
348 size_t ret = 0; // For compiling error
349
350 /****************************************************
351 format:
352 CMD: 01 01 FF LEN WR ADDR VALUE FILE_PATH
353 EVENT: 04 0E LEN 01 01 FF ERRNO WR ADDR VALUE
354
355 LEN: 1 byte
356 WR: 1 byte
357 ADDR: 4 bytes
358 VALUE: 1 byte
359 ERRNO: 2 bytes
360 FILE_PATH:
361 ****************************************************/
362
363 errno = 0;
364
365 fd = open((char *)&buf[10], O_RDWR);
366 if (fd < 0) {
367 printf("open file %s failed, errno = %s(%d)\n", &buf[10], strerror(errno), errno);
368 } else {
369 memcpy(&addr, &buf[5], sizeof(addr));
370 wr = buf[4];
371
372 (void)lseek(fd, addr, SEEK_SET);
373
374 if (wr == WR_FLAG_WRITE) {
375 value = buf[9];
376 ret = write(fd, &value, 1);
377 } else {
378 ret = read(fd, &value, 1);
379 }
380
381 close(fd);
382 }
383
384 buf[0] = 0x04;
385 buf[1] = 0x0E;
386 buf[2] = 0x0B;
387 buf[3] = 0x01;
388 buf[4] = 0x01;
389 buf[5] = 0xFF;
390 buf[6] = errno & 0xFF;
391 buf[7] = (errno & 0xFF00) >> 8;
392 buf[8] = wr;
393 memcpy(&buf[9], &addr, sizeof(addr));
394 buf[13] = value;
395 *len = 14;
396 return ret;
397}
398
399//--------------------------------------------------------------------------
400void boots_pkt_parsing(uint8_t *buf, size_t len)
401{
402 int i = 0;
403 float alpha_filter = 0;
404
405 if (!buf || !len) return;
406
407 if (buf[0] == HCI_EVENT_PKT) {
408 if (buf[1] == HCE_COMMAND_COMPLETE && len >= 7) {
409 switch (STREAM_TO_UINT16(buf + 4)) {
410 case 0x0C03: // RESET
411 BPRINT_I_RAW("(HCI_RESET)");
412 break;
413 case 0x1009: // Read BD address
414 if (len >= 13)
415 BPRINT_I_RAW("(Read BDADD: 0x%02X-%02X-%02X-%02X-%02X-%02X)",
416 buf[12], buf[11], buf[10], buf[9], buf[8], buf[7]);
417 break;
418 case 0xFC0D: // RF test
419 if (buf[2] == 20) { // length is 20 for RF RX results
420 uint32_t result = 0;
421
422 BPRINT_I_RAW("\n");
423 result = STREAM_TO_UINT32(buf + 7);
424 BPRINT_I_RAW("\t RX Packet Count: %d\n", result);
425 result = STREAM_TO_UINT32(buf + 11);
426 BPRINT_I_RAW("\t RX Error Rate: %f%%\n", (float)result / 1000000.f);
427 result = STREAM_TO_UINT32(buf + 15);
428 BPRINT_I_RAW("\t RX Byte Count: %d\n", result);
429 result = STREAM_TO_UINT32(buf + 19);
430 BPRINT_I_RAW("\t Bit Error Rate: %f%%", (float)result / 1000000.f);
431 }
432 break;
433 case 0x201F: // BLE RX test
434 BPRINT_I_RAW("\n");
435 if (buf[2] >= 6 && buf[6] == 0) {
436 uint16_t pktcount = STREAM_TO_UINT16(buf + 7);
437 BPRINT_I_RAW("\t RX Packet Count: %d", pktcount);
438 } else {
439 BPRINT_W("status or length is incorrect");
440 }
441 break;
442 case 0xFC61: // packet rssi
443 BPRINT_I_RAW("\n");
444 BPRINT_I_RAW("\t Packet handle is 0x%02X%02X, RSSI is %d\n", buf[8], buf[7], (int8_t)buf[9]);
445 break;
446 case 0xFCD1: // register read
447 BPRINT_I_RAW("(register addr: 0x%08X, value: 0x%02X%02X%02X%02X)", efuse_reg_wr.addr, buf[10], buf[9], buf[8], buf[7]);
448 break;
449 case 0xFF01: // file read/write
450 if (buf[6] == 0 && buf[7] == 0) {
451 if (buf[8] == WR_FLAG_READ)
452 BPRINT_I_RAW("(offset: 0x%02X%02X%02X%02X, value: 0x%02X)", buf[12], buf[11], buf[10], buf[9], buf[13]);
453 } else {
454 uint16_t err = buf[6] | (buf[7] << 8);
455 BPRINT_I_RAW("(Error(%d): %s)", err, strerror(err));
456 }
457 break;
458 case 0x1802: // loopback
459 BPRINT_I_RAW("(LOOP_BACK)");
460 break;
461 case 0xFCEA: // get xo mode
462 if (buf[7] == 0x00) {
463 BPRINT_I_RAW("(AX_MODE)");
464 } else if (buf[7] == 0x01) {
465 BPRINT_I_RAW("(BT_MODE)");
466 }
467 break;
468 }
469 } else if (buf[1] == HCE_INQUIRY_RESULT || buf[1] == HCE_INQUIRY_RESULT_WITH_RSSI
470 || buf[1] == HCE_EXT_INQUIRY_RESULT) {
471 BPRINT_I_RAW("(BDADDR:0x%02X-%02X-%02X-%02X-%02X-%02X",
472 buf[9], buf[8], buf[7], buf[6], buf[5], buf[4]);
473 if (buf[1] == HCE_INQUIRY_RESULT_WITH_RSSI || buf[1] == HCE_EXT_INQUIRY_RESULT) {
474 int8_t rssi = ~buf[17] + 1;
475 BPRINT_I_RAW(", RSSI:%s%d", buf[17] > 0x7F ? "-" : "",
476 buf[17] > 0x7F ? rssi : buf[17]);
477 }
478 if (buf[1] == HCE_EXT_INQUIRY_RESULT) {
479 size_t i = 18;
480 while (buf[i]) {
481 if (buf[i + 1] == 8 || buf[i + 1] == 9) {
482 char name[256] = {0};
483 memcpy(name, &buf[i + 2], buf[i] - 1);
484 name[buf[i] - 1] = '\0';
485 BPRINT_I_RAW(", Name:%s", name);
486 }
487 i += (buf[i] + 1);
488 }
489 }
490 BPRINT_I_RAW(")");
491 } else if (buf[1] == HCE_INQUIRY_COMPLETE) {
492 BPRINT_I_RAW("(Inquiry_Complete)");
493 } else if (buf[1] == HCE_CONNECTION_COMPLETE) {
494 if (buf[12] == 0x01) {
495 BPRINT_I_RAW("(Connection_Complete)(ConnHandle:0x%04X)(ACL)", (((buf[5] << 8) & 0xff00) | buf[4]));
496 } else if(buf[12] == 0x00) {
497 BPRINT_I_RAW("(Connection_Complete)(ConnHandle:0x%04X)(SCO)", (((buf[5] << 8) & 0xff00) | buf[4]));
498 } else {
499 BPRINT_I_RAW("(Connection_Complete)(ConnHandle:%d)", ((buf[5] << 8 & 0xff00) | buf[4]));
500 }
501 } else if (buf[1] == 0xE4 && efuse_reg_wr.wr_flag == WR_FLAG_READ) {
502 if ((efuse_reg_wr.addr / 16 * 4) != (buf[9] | (buf[10] << 8))) {
503 BPRINT_I_RAW("(Read efuse error!)");
504 } else {
505 int8_t offset = 9 + ((efuse_reg_wr.addr / 4) % 4) * 6 + 2 + (efuse_reg_wr.addr % 4);
506
507 BPRINT_I_RAW("(efuse addr: 0x%04X, value: 0x%02X)", efuse_reg_wr.addr, buf[offset]);
508 }
509 } else if (buf[1] == 0x4F && buf[2] == 0x50 && buf[3] == 0xCC) {
510 for (i = 0; i < 79 ; i++) {
511 if (rssi_setting.alpha_filter > 0) {
512 if (rssi_count == 0)
513 rssi_channels[i] += (int8_t)buf[4 + i] * -1;
514 else {
515 alpha_filter = 1.0 / rssi_setting.alpha_filter;
516 rssi_channels[i] = (int)((rssi_channels[i] * (1 - alpha_filter)) + ((int8_t)buf[4 + i] * -1 * alpha_filter));
517 }
518 } else {
519 rssi_channels[i] += (int8_t)buf[4 + i] * -1;
520 }
521 }
522 rssi_count++;
523 if (rssi_setting.report == false) {
524 if (rssi_count == rssi_setting.avg_package || rssi_setting.alpha_filter > 0) {
525 BPRINT_I_RAW("\nRSSI: \n");
526 for (i = 0; i < 79 ; i++) {
527 if (rssi_setting.alpha_filter == 0)
528 rssi_channels[i] = rssi_channels[i] / rssi_count;
529 if (i >= rssi_setting.ch_start && i <= rssi_setting.ch_end) {
530 BPRINT_I_RAW("% 4d ", rssi_channels[i]);
531 } else {
532 BPRINT_I_RAW(" ");
533 }
534 if ((i + 1) % 10 == 0 || i == 78) {
535 BPRINT_I_RAW("\n");
536 }
537 }
538 if (rssi_setting.one_shot == 1) {
539 boots_pkt_cleanup_report_rssi(1);
540 boots_write_stpbtfwlog("01 73 FD 01 00");
541 }
542 if (rssi_setting.alpha_filter == 0) {
543 for (i = 0; i < 79; i++)
544 rssi_channels[i] = 0;
545 rssi_count = 0;
546 }
547 }
548 }
549 }
550 }
551}
552
553size_t boots_pkt_handler_parse(uint8_t *buf, size_t len, pkt_list_s **pList)
554{
555 size_t i = 0;
556 size_t ret = 0;
557 pkt_list_s *list = NULL;
558 uint16_t show_len = BOOTS_MSG_LVL_DEFAULT <= BOOTS_MSG_LVL_INFO ? DEF_SHOW_LEN : 0xFFFF;
559
560 if (pList)
561 list = *pList;
562
563 if ((pList == NULL && !(buf[1] == 0x4F && buf[2] == 0x50 && buf[3] == 0xCC))||
564 (list && list->s_type != SCRIPT_STRESS && list->s_type != SCRIPT_LOOPBACK && list->s_type != SCRIPT_LPTIMER) ||
565 (list && (list->s_type == SCRIPT_STRESS || list->s_type == SCRIPT_LOOPBACK || list->s_type == SCRIPT_LPTIMER) && BOOTS_STRESS_SHOW_ALL_EVENT))
566 {
567 switch (buf[0]) {
568 case HCI_CMD_PKT:
569 BPRINT_I_RAW("\t CMD:");
570 break;
571 case HCI_ACL_PKT:
572 BPRINT_I_RAW("\t ACL:");
573 break;
574 case HCI_SCO_PKT:
575 BPRINT_I_RAW("\t SCO:");
576 break;
577 case HCI_EVENT_PKT:
578 BPRINT_I_RAW("\tEvent:");
579 break;
580 default:
581 BPRINT_E("Receive unknonw type %02X", buf[0]);
582 BPRINT_I_RAW(" Unknown %02X:", buf[0]);
583 exit(0);
584 }
585
586 // exclude extended
587 for (i = 1; i < len && i <= show_len; i++) {
588 BPRINT_I_RAW(" %02X", buf[i]);
589 }
590 BPRINT_I_RAW("%s ", len > show_len ? "..." : "");
591 boots_pkt_parsing(buf, len); // Parsing
592 BPRINT_I_RAW("\n");
593 }
594
595 if (len > 2 && buf[0] == HCI_EVENT_PKT) {
596 if (len >= (buf[2] + 3)) {
597 if (buf[1] == HCE_COMMAND_COMPLETE || buf[1] == HCE_INQUIRY_COMPLETE) {
598 // means received Command_Complete or Inquiry_Complete
599 ret = 0;
600 } else if (buf[1] == 0xE4 && buf[2] == 0x1E
601 && efuse_reg_wr.wr_flag == WR_FLAG_WRITE) {
602 if (pList) {
603 *pList = boots_efuse_write(list, &buf[9]);
604 if (*pList) ret = 1;
605 }
606 } else if (buf[1] == 0x4F && buf[2] == 0x50 && buf[3] == 0xCC) {
607 boots_pkt_parsing(buf, len); // Parsing
608 ret = 1;
609 } else {
610 ret = 1;
611 }
612 } else {
613 BPRINT_E("len = %d, buf[2] = %d", len, buf[2]);
614 ret = -1;
615 }
616 }
617 return ret;
618}
619
620//--------------------------------------------------------------------------
621size_t boots_pkt_handler(uint8_t *buf, size_t len, pkt_list_s **pList)
622{
623 UNUSED(boots_btif);
624 size_t i = 0;
625 size_t ret = 0;
626 pkt_list_s *list = NULL;
627 size_t pkt_len = 0;
628 uint8_t *buf_parse = 0;
629 size_t buf_index = 0;
630
631 if (!buf || !len) return 0;
632
633 buf_parse = &buf[0];
634
635 while (len > 0) {
636 if (HCI_CMD_PKT == buf_parse[0])
637 pkt_len = len;
638 else if (HCI_EVENT_PKT == buf_parse[0])
639 pkt_len = buf_parse[2] + HCI_EVENT_PKT_HDR_LEN;
640 else if (HCI_ACL_PKT == buf_parse[0])
641 pkt_len = (buf_parse[4] << 8) + buf_parse[3] + HCI_ACL_PKT_HDR_LEN;
642 else {
643 BPRINT_E("Receive unknonw type %02X %02X %02X %02X", buf_parse[0], buf_parse[1],buf_parse[2], buf_parse[3]);
644 exit(0);
645 }
646
647 if (boots_pkt_handler_parse(buf_parse, pkt_len, pList))
648 ret = 1;
649 len -= pkt_len;
650 buf_index += pkt_len;
651 buf_parse = &buf[buf_index];
652 }
653
654 if (pList)
655 list = *pList;
656
657 /** For next action */
658 if (list) {
659 if (list->p_type == HCI_EVENT_PKT && buf[0] == HCI_EVENT_PKT) {
660 if (memcmp(buf, list->u_cnt.data, list->len)) {
661 BPRINT_I("Received is not match with script");
662 BPRINT_I_RAW("\tScript:");
663 for (i = 0; i < list->len; i++)
664 BPRINT_I_RAW("%02X ", list->u_cnt.data[i]);
665 BPRINT_I_RAW("\n");
666
667 if (list->s_type == SCRIPT_WAITRX) {
668 // waiting specific RX
669 BPRINT_I("Retry to get specific event");
670 return 1;
671 }
672 boots_pkt_list_destroy(list);
673 *pList = NULL;
674 return 0;
675
676 }
677 *pList = boots_pkt_node_pop(list, NULL, NULL);
678 }
679 if (*pList) ret = 1;
680 }
681 return ret;
682}
683
684//---------------------------------------------------------------------------
685static void boots_write_stpbtfwlog(char *buf)
686{
687 int fd = -1;
688
689 fd = open("/dev/stpbtfwlog", O_WRONLY);
690 if (fd < 0) {
691 BPRINT_E("Open /dev/stpbtfwlog fail");
692 return;
693 }
694 write(fd, buf, strlen(buf));
695 close(fd);
696}
697
698//--------------------------------------------------------------------------
699static pkt_list_s *mtk_boots_cmd_reset(char *cmd[], size_t len)
700{
701 uint8_t reset[] = {0x01, 0x03, 0x0C, 0x00};
702 pkt_list_s *node = NULL;
703
704 BPRINT_D("%s", __func__);
705 if (len == 2 && *(cmd[1] + 1) == 'h')
706 return NULL;
707
708 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, reset, sizeof(reset),
709 NULL, NULL);
710 return node;
711}
712
713//---------------------------------------------------------------------------
714static pkt_list_s *mtk_boots_cmd_inquiry(char *cmd[], size_t len)
715{
716 uint8_t inq_mode[] = {0x01, 0x45, 0x0C, 0x01, 0x02};
717 uint8_t inq[] = {0x01, 0x01, 0x04, 0x05, 0x33, 0x8B, 0x9E, 2, 0x00};
718 pkt_list_s *list = NULL;
719
720 BPRINT_D("%s", __func__);
721 if (len > 2 && *(cmd[1] + 1) == 't') {
722 inq[7] = strtol(cmd[2], NULL, 16);
723 } else if (len > 1) {
724 return NULL;
725 }
726 list = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, inq_mode, sizeof(inq_mode),
727 NULL, NULL);
728 if (list)
729 boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, inq, sizeof(inq), list, list);
730 return list;
731}
732
733//---------------------------------------------------------------------------
734static pkt_list_s *mtk_boots_cmd_enter_dut(char *cmd[], size_t len)
735{
736 uint8_t reset[] = {0x01, 0x03, 0x0C, 0x00};
737 uint8_t scan_enable[] = {0x01, 0x1A, 0x0C, 0x01, 0x03};
738 uint8_t event_filter[] = {0x01, 0x05, 0x0C, 0x03, 0x02, 0x00, 0x02};
739 uint8_t dut[] = {0x01, 0x03, 0x18, 0x00};
740 pkt_list_s *list = NULL;
741 pkt_list_s *tmp = NULL;
742
743 BPRINT_D("%s", __func__);
744 if (len == 2 && *(cmd[1] + 1) == 'h')
745 return NULL;
746
747 list = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, reset, sizeof(reset),
748 NULL, NULL);
749 if (list)
750 tmp = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, scan_enable,
751 sizeof(scan_enable), list, list);
752 if (tmp)
753 tmp = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, event_filter,
754 sizeof(event_filter), tmp, list);
755 if (tmp)
756 boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, dut, sizeof(dut), tmp, list);
757
758 return list;
759}
760
761//---------------------------------------------------------------------------
762static pkt_list_s *mtk_boots_cmd_read_bd_addr(char *cmd[], size_t len)
763{
764 uint8_t raddr[] = {0x01, 0x09, 0x10, 0x00};
765 pkt_list_s *node = NULL;
766
767 BPRINT_D("%s", __func__);
768 if (len == 2 && *(cmd[1] + 1) == 'h')
769 return NULL;
770
771 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, raddr, sizeof(raddr),
772 NULL, NULL);
773 return node;
774}
775
776//---------------------------------------------------------------------------
777static pkt_list_s *mtk_boots_cmd_write_bd_addr(char *cmd[], size_t len)
778{
779 uint8_t waddr[] = {0x01, 0x1A, 0xFC, 0x06, 0, 0, 0, 0, 0, 0};
780 pkt_list_s *node = NULL;
781
782 BPRINT_D("%s", __func__);
783 if (len == 2 && *(cmd[1] + 1) == 'h')
784 return NULL;
785
786 if (len >= 2 && strlen(cmd[1]) == 17) {
787 waddr[9] = strtol(cmd[1], NULL, 16);
788 waddr[8] = strtol(cmd[1] + 3, NULL, 16);
789 waddr[7] = strtol(cmd[1] + 6, NULL, 16);
790 waddr[6] = strtol(cmd[1] + 9, NULL, 16);
791 waddr[5] = strtol(cmd[1] + 12, NULL, 16);
792 waddr[4] = strtol(cmd[1] + 15, NULL, 16);
793 /** Don't suppport separated address
794 } else if (len == 7) {
795 int i = 0;
796 for (i = 0; i < 6; i++)
797 waddr[9 - i] = strtol(cmd[i + 1], NULL, 16);
798 */
799 } else {
800 BPRINT_E("%s: Incorrect format", __func__);
801 return NULL;
802 }
803 if (!waddr[4] && !waddr[5] && !waddr[6] && !waddr[7] && !waddr[8] && !waddr[9]) {
804 BPRINT_E("%s: Incorrect format", __func__);
805 return NULL;
806 }
807 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, waddr, sizeof(waddr),
808 NULL, NULL);
809 return node;
810}
811
812//---------------------------------------------------------------------------
813static pkt_list_s *mtk_boots_cmd_set_power_level(char *cmd[], size_t len)
814{
815 uint8_t power_level[] = {0x01, 0x17, 0xFC, 0x04, 0x00, 0x00, 0, 0x00};
816 pkt_list_s *node = NULL;
817
818 BPRINT_D("%s", __func__);
819 if (len == 2 && *(cmd[1] + 1) == 'h') {
820 return NULL;
821 } else if (len < 2) {
822 BPRINT_E("%s: Incorrect format", __func__);
823 return NULL;
824 }
825
826 power_level[6] = strtol(cmd[1], NULL, 16);
827 if (power_level[6] > 9 || (power_level[6] == 0 && *cmd[1] != '0')) {
828 BPRINT_E("%s: Incorrect format", __func__);
829 return NULL;
830 }
831 BPRINT_W("%s: NOTE, this command only affects RFTX", __func__);
832 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, power_level,
833 sizeof(power_level), NULL, NULL);
834 return node;
835}
836
837//---------------------------------------------------------------------------
838static pkt_list_s *mtk_boots_cmd_set_whiten(char *cmd[], size_t len)
839{
840 uint8_t whiten[] = {0x01, 0x15, 0xFC, 0x01, 0};
841 pkt_list_s *node = NULL;
842
843 BPRINT_D("%s", __func__);
844 if (len == 2 && *(cmd[1] + 1) == 'h') {
845 return NULL;
846 } else if (len < 2) {
847 BPRINT_E("%s: Incorrect format", __func__);
848 return NULL;
849 }
850
851 whiten[4] = strtol(cmd[1], NULL, 16);
852 if (whiten[4] > 1 || (whiten[4] == 0 && *cmd[1] != '0')) {
853 BPRINT_E("%s: Incorrect format", __func__);
854 return NULL;
855 }
856 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, whiten, sizeof(whiten),
857 NULL, NULL);
858 return node;
859}
860
861//---------------------------------------------------------------------------
862static pkt_list_s *mtk_boots_cmd_rf_tx(char *cmd[], size_t len)
863{
864 uint8_t rf_test[] = {0x01, 0x0D, 0xFC, 0x17, 0x00, 0x00,
865 0, // pattern
866 1, // hopping:1, fixed channel:0
867 0, // channel if fixed
868 0, // channel if fixed
869 0x00,
870 0x02, // poll period, unit: 1.25ms
871 0, // packet type
872 0, 0, // packet length
873 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
874 pkt_list_s *node = NULL;
875 size_t i = 1, j = 0;
876
877 BPRINT_D("%s", __func__);
878 if (len == 2 && *(cmd[1] + 1) == 'h') {
879 return NULL;
880 } else if (!(len % 2)) {
881 BPRINT_E("%s: Incorrect format", __func__);
882 return NULL;
883 }
884
885 while (i + 1 < len) {
886 switch (*(cmd[i] + 1)) {
887 case 'p': // Pattern
888 rf_test[6] = strtol(cmd[i + 1], NULL, 16);
889 if (rf_test[6] == 0x0A) {
890 rf_test[7] = 0; // fix channel
891 } else if (rf_test[6] != 1 && rf_test[6] != 2 && rf_test[6] != 3
892 && rf_test[6] != 4 && rf_test[6] != 9 && rf_test[6] != 0xa) {
893 BPRINT_E("%s: Incorrect format: -p %s", __func__, cmd[i + 1]);
894 return NULL;
895 }
896 i += 2;
897 break;
898 case 'c': // channel
899 rf_test[7] = 0;
900 rf_test[8] = strtol(cmd[i + 1], NULL, 10);
901 rf_test[9] = rf_test[8];
902 if (rf_test[8] > 78) {
903 BPRINT_E("%s: Incorrect format: -c %s", __func__, cmd[i + 1]);
904 return NULL;
905 }
906 i += 2;
907 break;
908 case 't': // packet type
909 rf_test[12] = strtol(cmd[i + 1], NULL, 16);
910 while (j < ARRAY_SIZE(tx_pi)) {
911 if (tx_pi[j].pt == rf_test[12])
912 break;
913 else
914 j++;
915 }
916 if (j >= ARRAY_SIZE(tx_pi)) {
917 BPRINT_E("%s: Incorrect format: -t %s", __func__, cmd[i + 1]);
918 return NULL;
919 }
920 if (STREAM_TO_UINT16(rf_test + 13) == 0)
921 UINT16_TO_STREAM(rf_test + 13, tx_pi[j].len);
922 i += 2;
923 BPRINT_D("t/l: %02X %02X", rf_test[13], rf_test[14]);
924 break;
925 case 'l':
926 UINT16_TO_STREAM(rf_test + 13, strtol(cmd[i + 1], NULL, 10));
927 i += 2;
928 BPRINT_D("l: %02X %02X", rf_test[13], rf_test[14]);
929 break;
930 case 'o': // Period
931 rf_test[11] = (uint8_t)strtol(cmd[i + 1], NULL, 10);
932 if (rf_test[11] < 1 || rf_test[11] > 255) {
933 BPRINT_E("%s: Incorrect format: -o %s", __func__, cmd[i + 1]);
934 return NULL;
935 }
936 i += 2;
937 break;
938 default:
939 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
940 return NULL;
941 }
942 }
943
944 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, rf_test,
945 sizeof(rf_test), NULL, NULL);
946 return node;
947}
948
949//---------------------------------------------------------------------------
950static pkt_list_s *mtk_boots_cmd_rf_rx(char *cmd[], size_t len)
951{
952 uint8_t rf_test[] = {0x01, 0x0D, 0xFC, 0x17, 0x00,
953 0, // pattern
954 0x0B, // rx start:0x0B, rx stop:0xFF, rx result:0x0C
955 0x00, 0x00,
956 0, // channel
957 0x00, 0x01,
958 3, // packet type
959 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
960 0x00, 0xA5, 0xF0, 0xC3, // address
961 0x00, 0x00};
962 pkt_list_s *node = NULL;
963 size_t i = 1, j = 0;
964
965 BPRINT_D("%s: %s", __func__, cmd[0]);
966 if (len == 2 && *(cmd[1] + 1) == 'h') {
967 return NULL;
968 } else if (!(len % 2)) {
969 BPRINT_E("%s: Incorrect format", __func__);
970 return NULL;
971 }
972
973 if (!memcmp("rfr_stop", cmd[0], strlen("rfr_stop"))) {
974 rf_test[6] = 0xFF;
975 }
976
977 if (!memcmp("rfr_result", cmd[0], strlen("rfr_result"))) {
978 rf_test[6] = 0x0C;
979 }
980
981 while (i + 1 < len) {
982 switch (*(cmd[i] + 1)) {
983 case 'p': // Pattern
984 rf_test[5] = strtol(cmd[i + 1], NULL, 16);
985 if (rf_test[5] != 1 && rf_test[5] != 2 && rf_test[5] != 3
986 && rf_test[5] != 4 && rf_test[5] != 9) {
987 BPRINT_E("%s: Incorrect format: -p %s", __func__, cmd[i + 1]);
988 return NULL;
989 }
990 i += 2;
991 break;
992 case 'c': // channel
993 rf_test[9] = strtol(cmd[i + 1], NULL, 10);
994 if (rf_test[9] > 78) {
995 BPRINT_E("%s: Incorrect format: -c %s", __func__, cmd[i + 1]);
996 return NULL;
997 }
998 i += 2;
999 break;
1000 case 't': // packet type
1001 rf_test[12] = strtol(cmd[i + 1], NULL, 16);
1002 while (j < ARRAY_SIZE(rx_pi)) {
1003 if (rx_pi[j].pt == rf_test[12])
1004 break;
1005 else
1006 j++;
1007 }
1008 if (j >= ARRAY_SIZE(rx_pi)) {
1009 BPRINT_E("%s: Incorrect format: -t %s", __func__, cmd[i + 1]);
1010 return NULL;
1011 }
1012 i += 2;
1013 break;
1014 case 'a':
1015 if (strlen(cmd[i + 1]) == 11) {
1016 rf_test[21] = strtol(cmd[i + 1], NULL, 16);
1017 rf_test[22] = strtol(cmd[i + 1] + 3, NULL, 16);
1018 rf_test[23] = strtol(cmd[i + 1] + 6, NULL, 16);
1019 rf_test[24] = strtol(cmd[i + 1] + 9, NULL, 16);
1020 } else {
1021 BPRINT_E("%s: Incorrect format", __func__);
1022 return NULL;
1023 }
1024 if (!rf_test[21] && !rf_test[22] && !rf_test[23] && !rf_test[24]) {
1025 BPRINT_E("%s: Incorrect format", __func__);
1026 return NULL;
1027 }
1028 i += 2;
1029 break;
1030 default:
1031 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1032 return NULL;
1033 }
1034 }
1035
1036 if (!rf_test[21] && !rf_test[22] && !rf_test[23] && !rf_test[24]) {
1037 BPRINT_E("Please input Tester Address");
1038 return NULL;
1039 }
1040 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, rf_test,
1041 sizeof(rf_test), NULL, NULL);
1042 return node;
1043}
1044
1045//---------------------------------------------------------------------------
1046static pkt_list_s *mtk_boots_cmd_rf_stop(char *cmd[], size_t len)
1047{
1048 uint8_t rf_stop[] = {0x01, 0x0D, 0xFC, 0x17, 0x00, 0x00,
1049 0xFF, /* 0xFF: rf stop */
1050 0x00, 0x00,
1051 0x00,
1052 0x00, 0x00,
1053 0x00,
1054 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
1055 0x00, 0x00, 0x00, 0x00,
1056 0x00, 0x00};
1057 pkt_list_s *node = NULL;
1058
1059 BPRINT_D("%s", __func__);
1060 if (len == 2 && *(cmd[1] + 1) == 'h') {
1061 return NULL;
1062 }
1063
1064 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, rf_stop,
1065 sizeof(rf_stop), NULL, NULL);
1066 return node;
1067}
1068
1069//---------------------------------------------------------------------------
1070static pkt_list_s *mtk_boots_cmd_ble_tx(char *cmd[], size_t len)
1071{
1072 uint8_t ble_tx[] = {0x01, 0x1E, 0x20, 0x03, 0, 37, 0};
1073 uint16_t length = 0;
1074 pkt_list_s *node = NULL;
1075 size_t i = 1;
1076
1077 BPRINT_D("%s", __func__);
1078 if (len == 2 && *(cmd[1] + 1) == 'h') {
1079 return NULL;
1080 } else if (!(len % 2)) {
1081 BPRINT_E("%s: Incorrect format", __func__);
1082 return NULL;
1083 }
1084
1085 while (i + 1 < len) {
1086 switch (*(cmd[i] + 1)) {
1087 case 'c': // Channel
1088 ble_tx[4] = strtol(cmd[i + 1], NULL, 10);
1089 if (ble_tx[4] > 39) {
1090 BPRINT_E("%s: Incorrect format: -c %s", __func__, cmd[i + 1]);
1091 return NULL;
1092 }
1093 i += 2;
1094 break;
1095 case 'p': // Pattern
1096 ble_tx[6] = strtol(cmd[i + 1], NULL, 16);
1097 if (ble_tx[6] > 7) {
1098 BPRINT_E("%s: Incorrect format: -p %s", __func__, cmd[i + 1]);
1099 return NULL;
1100 }
1101 i += 2;
1102 break;
1103 case 'l': // length
1104 length = strtol(cmd[i + 1], NULL, 10);
1105 if ((length == 0 && strtol(cmd[i + 1], NULL, 16) != 0) || length > 255) {
1106 BPRINT_E("%s: Incorrect format: -l %s", __func__, cmd[i + 1]);
1107 return NULL;
1108 }
1109 ble_tx[5] = length;
1110 i += 2;
1111 break;
1112 default:
1113 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1114 return NULL;
1115 }
1116 }
1117
1118 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, ble_tx, sizeof(ble_tx),
1119 NULL, NULL);
1120
1121 return node;
1122}
1123
1124//---------------------------------------------------------------------------
1125static pkt_list_s *mtk_boots_cmd_ble_rx(char *cmd[], size_t len)
1126{
1127 uint8_t ble_rx[] = {0x01, 0x1D, 0x20, 0x01, 0 /* channel */};
1128 pkt_list_s *node = NULL;
1129 size_t i = 1;
1130
1131 BPRINT_D("%s", __func__);
1132 if (len == 2 && *(cmd[1] + 1) == 'h') {
1133 return NULL;
1134 } else if (!(len % 2)) {
1135 BPRINT_E("%s: Incorrect format", __func__);
1136 return NULL;
1137 }
1138
1139 while (i + 1 < len) {
1140 switch (*(cmd[i] + 1)) {
1141 case 'c': // Channel
1142 ble_rx[4] = strtol(cmd[i + 1], NULL, 10);
1143 if (ble_rx[4] > 39) {
1144 BPRINT_E("%s: Incorrect format: -c %s", __func__, cmd[i + 1]);
1145 return NULL;
1146 }
1147 i += 2;
1148 break;
1149 default:
1150 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1151 return NULL;
1152 }
1153 }
1154
1155 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, ble_rx, sizeof(ble_rx),
1156 NULL, NULL);
1157
1158 return node;
1159}
1160
1161//--------------------------------------------------------------------------
1162static pkt_list_s *mtk_boots_cmd_ble_test_stop(char *cmd[], size_t len)
1163{
1164 uint8_t ble_stop[] = {0x01, 0x1F, 0x20, 0x00};
1165 pkt_list_s *node = NULL;
1166
1167 BPRINT_D("%s", __func__);
1168 if (len == 2 && *(cmd[1] + 1) == 'h')
1169 return NULL;
1170
1171 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, ble_stop, sizeof(ble_stop), NULL, NULL);
1172 return node;
1173}
1174
1175//---------------------------------------------------------------------------
1176static pkt_list_s *mtk_boots_cmd_ble_etx(char *cmd[], size_t len)
1177{
1178 uint8_t ble_etx[] = {0x01, 0x34, 0x20, 0x04, 0, 0, 0, 1};
1179 uint16_t length = 0;
1180 pkt_list_s *node = NULL;
1181 size_t i = 1;
1182
1183 BPRINT_D("%s", __func__);
1184 if (len == 2 && *(cmd[1] + 1) == 'h') {
1185 return NULL;
1186 } else if (!(len % 2)) {
1187 BPRINT_E("%s: Incorrect format", __func__);
1188 return NULL;
1189 }
1190
1191 while (i + 1 < len) {
1192 switch (*(cmd[i] + 1)) {
1193 case 'c': // Channel
1194 ble_etx[4] = strtol(cmd[i + 1], NULL, 10);
1195 if (ble_etx[4] > 39) {
1196 BPRINT_E("%s: Incorrect format: -c %s", __func__, cmd[i + 1]);
1197 return NULL;
1198 }
1199 break;
1200 case 'l': // Packet length in bytes
1201 length = strtol(cmd[i + 1], NULL, 10);
1202 if ((length == 0 && strtol(cmd[i + 1], NULL, 16) != 0) || length > 255) {
1203 BPRINT_E("%s: Incorrect format: -l %s", __func__, cmd[i + 1]);
1204 return NULL;
1205 }
1206 ble_etx[5] = length;
1207 break;
1208 case 'p': // Packet Payload
1209 ble_etx[6] = strtol(cmd[i + 1], NULL, 10);
1210 if (ble_etx[6] > 0x07) { // So far 0x08-0xFF reserved for future use
1211 BPRINT_E("%s: Incorrect format: -p %s", __func__, cmd[i + 1]);
1212 return NULL;
1213 }
1214 break;
1215 case 'y': // PHY
1216 ble_etx[7] = strtol(cmd[i + 1], NULL, 10);
1217 if (ble_etx[7] == 0 || ble_etx[7] > 0x05) { // So far 0 and 0x05-0xFF reserved for future use
1218 BPRINT_E("%s: Incorrect format: -y %s", __func__, cmd[i + 1]);
1219 return NULL;
1220 }
1221 break;
1222 default:
1223 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1224 return NULL;
1225 }
1226 i += 2;
1227 }
1228
1229 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, ble_etx, sizeof(ble_etx),
1230 NULL, NULL);
1231
1232 return node;
1233}
1234
1235//---------------------------------------------------------------------------
1236static pkt_list_s *mtk_boots_cmd_ble_erx(char *cmd[], size_t len)
1237{
1238 uint8_t ble_erx[] = {0x01, 0x33, 0x20, 0x03, 0, 1, 0};
1239 pkt_list_s *node = NULL;
1240 size_t i = 1;
1241
1242 BPRINT_D("%s", __func__);
1243 if (len == 2 && *(cmd[1] + 1) == 'h') {
1244 return NULL;
1245 } else if (!(len % 2)) {
1246 BPRINT_E("%s: Incorrect format", __func__);
1247 return NULL;
1248 }
1249
1250 while (i + 1 < len) {
1251 switch (*(cmd[i] + 1)) {
1252 case 'c': // Channel
1253 ble_erx[4] = strtol(cmd[i + 1], NULL, 10);
1254 if (ble_erx[4] > 39) {
1255 BPRINT_E("%s: Incorrect format: -c %s", __func__, cmd[i + 1]);
1256 return NULL;
1257 }
1258 break;
1259 case 'y': // PHY
1260 ble_erx[5] = strtol(cmd[i + 1], NULL, 10);
1261 /** So far 0 and 0x04-0xFF reserved for future use
1262 7668/6632 not support 0x03:LE Coded PHY */
1263 if (ble_erx[5] == 0 || ble_erx[5] > 0x04) {
1264 BPRINT_E("%s: Incorrect format: -y %s", __func__, cmd[i + 1]);
1265 return NULL;
1266 }
1267 break;
1268 case 'm': // Modulation Index
1269 ble_erx[6] = strtol(cmd[i + 1], NULL, 10);
1270 if (ble_erx[6] > 0x01) {
1271 BPRINT_E("%s: Incorrect format: -m %s", __func__, cmd[i + 1]);
1272 return NULL;
1273 }
1274 break;
1275 default:
1276 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1277 return NULL;
1278 }
1279 i += 2;
1280 }
1281
1282 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, ble_erx, sizeof(ble_erx),
1283 NULL, NULL);
1284
1285 return node;
1286}
1287//---------------------------------------------------------------------------
1288static pkt_list_s *mtk_boots_cmd_tx_tone(char *cmd[], size_t len)
1289{
1290 uint8_t txtone[] = {0x01, 0xD5, 0xFC, 0x05, 0, 0, 0, 0, 0};
1291 pkt_list_s *node = NULL;
1292 size_t i = 1;
1293
1294 BPRINT_D("%s", __func__);
1295 if (len == 2 && *(cmd[1] + 1) == 'h') {
1296 return NULL;
1297 } else if (!(len % 2)) {
1298 BPRINT_E("%s: Incorrect format", __func__);
1299 return NULL;
1300 }
1301
1302 while (i + 1 < len) {
1303 switch (*(cmd[i] + 1)) {
1304 case 't': // Tone Type
1305 txtone[5] = strtol(cmd[i + 1], NULL, 10);
1306 if (txtone[5] > 4) {
1307 BPRINT_E("%s: Incorrect format: -t %s", __func__, cmd[i + 1]);
1308 return NULL;
1309 }
1310 i += 2;
1311 break;
1312 case 'c': // TX frequency
1313 txtone[4] = strtol(cmd[i + 1], NULL, 10);
1314 if (txtone[4] > 78) {
1315 BPRINT_E("%s: Incorrect format: -c %s", __func__, cmd[i + 1]);
1316 return NULL;
1317 }
1318 i += 2;
1319 break;
1320 case 'm': // Mode
1321 txtone[6] = strtol(cmd[i + 1], NULL, 10);
1322 if (txtone[6] > 1) {
1323 BPRINT_E("%s: Incorrect format: -m %s", __func__, cmd[i + 1]);
1324 return NULL;
1325 }
1326 i += 2;
1327 break;
1328 case 'd': // Modulation Type
1329 txtone[7] = strtol(cmd[i + 1], NULL, 10);
1330 if (txtone[7] > 6) {
1331 BPRINT_E("%s: Incorrect format: -d %s", __func__, cmd[i + 1]);
1332 return NULL;
1333 }
1334 i += 2;
1335 break;
1336 case 'p': // Pattern Type
1337 txtone[8] = strtol(cmd[i + 1], NULL, 10);
1338 if (txtone[8] > 1) {
1339 BPRINT_E("%s: Incorrect format: -p %s", __func__, cmd[i + 1]);
1340 return NULL;
1341 }
1342 i += 2;
1343 break;
1344 default:
1345 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1346 return NULL;
1347 }
1348 }
1349
1350 if (txtone[5] <= 3) {
1351 // Only for Modulation Tone
1352 txtone[6] = txtone[7] = txtone[8] = 0;
1353 } else if (txtone[6] == 1) {
1354 // Only for BT mode
1355 txtone[7] = 0;
1356 }
1357
1358 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, txtone, sizeof(txtone),
1359 NULL, NULL);
1360 return node;
1361}
1362
1363//---------------------------------------------------------------------------
1364static pkt_list_s *mtk_boots_cmd_radio_setting(char *cmd[], size_t len)
1365{
1366 uint8_t set_radio[] = {0x01, 0x79, 0xFC, 0x08,
1367 7, 0x00, 0x00, 0x00, 7, 7, 0, 0};
1368 pkt_list_s *node = NULL;
1369 size_t i = 1;
1370
1371 BPRINT_D("%s", __func__);
1372 if (len == 2 && *(cmd[1] + 1) == 'h') {
1373 return NULL;
1374 } else if (!(len % 2)) {
1375 BPRINT_E("%s: Incorrect format", __func__);
1376 return NULL;
1377 }
1378 /**
1379 * for 7668, 7663
1380 * Level: radio setting -b <0~7> -e <0~7> -m <0~7> -s <0~3> -o <0/1>
1381 */
1382
1383 while (i + 1 < len) {
1384 switch (*(cmd[i] + 1)) {
1385 case 'b': // BT TX power level
1386 set_radio[4] = strtol(cmd[i + 1], NULL, 10);
1387 if (set_radio[4] > 7 || set_radio[4] < 0) {
1388 BPRINT_E("%s: Incorrect format: -b %s", __func__, cmd[i + 1]);
1389 return NULL;
1390 }
1391 i += 2;
1392 break;
1393 case 'e': // BLE TX power level
1394 set_radio[8] = strtol(cmd[i + 1], NULL, 10);
1395 if (set_radio[8] > 7 || set_radio[8] < 0) {
1396 BPRINT_E("%s: Incorrect format: -e %s", __func__, cmd[i + 1]);
1397 return NULL;
1398 }
1399 i += 2;
1400 break;
1401 case 'm': // MAX TX power level
1402 set_radio[9] = strtol(cmd[i + 1], NULL, 10);
1403 if (set_radio[9] > 7 || set_radio[9] < 0) {
1404 BPRINT_E("%s: Incorrect format: -m %s", __func__, cmd[i + 1]);
1405 return NULL;
1406 }
1407 i += 2;
1408 break;
1409 case 's': // 1db adjust
1410 set_radio[10] = strtol(cmd[i + 1], NULL, 10);
1411 if (set_radio[10] > 3 || set_radio[10] < 0) {
1412 BPRINT_E("%s: Incorrect format: -s %s", __func__, cmd[i + 1]);
1413 return NULL;
1414 }
1415 i += 2;
1416 break;
1417 case 'o': // 3db diff mode
1418 set_radio[11] = strtol(cmd[i + 1], NULL, 10);
1419 if (set_radio[11] > 1 || set_radio[11] < 0) {
1420 BPRINT_E("%s: Incorrect format: -o %s", __func__, cmd[i + 1]);
1421 return NULL;
1422 }
1423 i += 2;
1424 break;
1425 default:
1426 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1427 return NULL;
1428 }
1429 }
1430
1431 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, set_radio, sizeof(set_radio),
1432 NULL, NULL);
1433 return node;
1434}
1435
1436//---------------------------------------------------------------------------
1437static pkt_list_s *mtk_boots_cmd_tx_power_setting(char *cmd[], size_t len)
1438{
1439 int8_t set_txpow[] = {0x01, 0x2C, 0xFC, 0x08,
1440 7, 0x00, 0x00, 0x00, 7, 7, 0, 0};
1441 pkt_list_s *node = NULL;
1442 size_t i = 1;
1443
1444 BPRINT_D("%s", __func__);
1445 if (len == 2 && *(cmd[1] + 1) == 'h') {
1446 return NULL;
1447 } else if (!(len % 2)) {
1448 BPRINT_E("%s: Incorrect format", __func__);
1449 return NULL;
1450 }
1451 /**
1452 * for Buzzard
1453 * dbm: radio setting -b <-32~12> -e <-29~20> -m <-32~12> -n <0/1> -o <0/1>
1454 */
1455
1456 while (i + 1 < len) {
1457 switch (*(cmd[i] + 1)) {
1458 case 'b': // EDR init TX power dbm
1459 set_txpow[4] = strtol(cmd[i + 1], NULL, 10);
1460 if (set_txpow[4] > 12 || set_txpow[4] < -32) {
1461 BPRINT_E("%s: Incorrect format: -b %s", __func__, cmd[i + 1]);
1462 return NULL;
1463 }
1464 i += 2;
1465 break;
1466 case 'e': // BLE TX power dbm
1467 set_txpow[8] = strtol(cmd[i + 1], NULL, 10);
1468 if (set_txpow[8] > 20 || set_txpow[8] < -29) {
1469 BPRINT_E("%s: Incorrect format: -e %s", __func__, cmd[i + 1]);
1470 return NULL;
1471 }
1472 i += 2;
1473 break;
1474 case 'm': // ECR Max TX power dbm
1475 set_txpow[9] = strtol(cmd[i + 1], NULL, 10);
1476 if (set_txpow[9] > 12 || set_txpow[9] < -32) {
1477 BPRINT_E("%s: Incorrect format: -m %s", __func__, cmd[i + 1]);
1478 return NULL;
1479 }
1480 i += 2;
1481 break;
1482 case 'n': // enable Lv9
1483 set_txpow[10] = strtol(cmd[i + 1], NULL, 10);
1484 if (set_txpow[10] > 1 || set_txpow[10] < 0) {
1485 BPRINT_E("%s: Incorrect format: -n %s", __func__, cmd[i + 1]);
1486 return NULL;
1487 }
1488 i += 2;
1489 break;
1490 case 'o': // 3db diff mode
1491 set_txpow[11] = strtol(cmd[i + 1], NULL, 10);
1492 if (set_txpow[11] > 1 || set_txpow[11] < 0) {
1493 BPRINT_E("%s: Incorrect format: -o %s", __func__, cmd[i + 1]);
1494 return NULL;
1495 }
1496 i += 2;
1497 break;
1498 default:
1499 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1500 return NULL;
1501 }
1502 }
1503
1504 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, set_txpow, sizeof(set_txpow),
1505 NULL, NULL);
1506 return node;
1507}
1508
1509//---------------------------------------------------------------------------
1510static pkt_list_s *mtk_boots_cmd_tx_power_offset(char *cmd[], size_t len)
1511{
1512 /* 4 is header, 7668 MAX has 22 bytes, 7663 MAX has 20 bytes */
1513 uint8_t txpoweroffset[] = {0x01, 0x93, 0xFC, 0x06,
1514 /* g: power offset, for 7662/7668 only 6 groups, but in 7663 have 16 */
1515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1516 /* r/i: power offset/PDC value for level 8 ONLY for 7668. */
1517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1518 /* e: ePA offset ONLY for 7668 */
1519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1520 uint8_t hybridmode[] = {0x01, 0x74, 0xFD, 0x01, 0x02};
1521 pkt_list_s *list = NULL;
1522 pkt_list_s *node = NULL;
1523 size_t i = 1;
1524 size_t cmd_len = 10; /* 16 bytes command supporting since 2018/5, 22 bytes command supporting since 2018/7 */
1525 int8_t temp = 0x00;
1526 uint8_t lvl_8_temp[] = {0, 0, 0, 0, 0, 0};
1527 bool hybrid = false;
1528 bool lvl_8 = false;
1529 bool pwr16 = false; /* false: 7662/7668 has 6 groups., true: 7663 has 16 groups */
1530
1531 BPRINT_D("%s", __func__);
1532 if (len == 2 && *(cmd[1] + 1) == 'h') {
1533 return NULL;
1534 } else if (!(len % 2) && memcmp(cmd[1], "g16", strlen("g16")) != 0) {
1535 BPRINT_E("%s: Incorrect format", __func__);
1536 return NULL;
1537 }
1538 /**
1539 * TX power offset -g0 <-16~16> -g1 <-16~16> -g2 <-16~16>
1540 * -g3 <-16~16> -g4 <-16~16> -g5 <-16~16> ...
1541 * TX power offset for ePA -e0 <-16~8> -e1 <-16~8> -e2 <-16~8>
1542 * -e3 <-16~8> -e4 <-16~8> -e5 <-16~8>
1543 * TX power offset for level 8 RFCR -r0 <-2~4> -r1 <-2~4> -r2 <-2~4>
1544 * -r3 <-2~4> -r4 <-2~4> -r5 <-2~4>
1545 * TX power offset for level 8 DPC -i0 <-6~6> -i1 <-6~6> -i2 <-6~6>
1546 * -i3 <-6~6> -i4 <-6~6> -i5 <-6~6>
1547 * One step is +/-0.25dbm
1548 */
1549
1550 if (memcmp(cmd[i], "g16", strlen("g16")) == 0) {
1551 pwr16 = true;
1552 i++;
1553 }
1554
1555 while (i + 1 < len) {
1556 switch (*(cmd[i] + 1)) {
1557 case 'g': { // Tone Type
1558 uint8_t gpidx = strtol(cmd[i] + 2, NULL, 10);
1559
1560 if (hybrid == true) {
1561 BPRINT_E("%s: Incorrect format: %s - You are in hybrid mode", __func__, cmd[i]);
1562 return NULL;
1563 }
1564 if (gpidx < 16 && gpidx > 5)
1565 pwr16 = true;
1566 else if (gpidx >= 16) {
1567 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1568 return NULL;
1569 }
1570 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
1571 if (temp > 16 || temp < -16) {
1572 BPRINT_E("%s: Incorrect range: %s %d", __func__, cmd[i], temp);
1573 return NULL;
1574 }
1575 txpoweroffset[gpidx + 4] = temp;
1576 i += 2;
1577 } break;
1578 case 'r': // lvl 8 offset RFCR value
1579 if (pwr16 == true) {
1580 BPRINT_E("%s: Incorrect format: %s - 7668 groups should only 0~5", __func__, cmd[i]);
1581 return NULL;
1582 }
1583
1584 if (cmd_len == 10) {
1585 cmd_len = 22;
1586 txpoweroffset[3] = 0x12;
1587 }
1588 hybrid = true;
1589 lvl_8 = true;
1590 switch (*(cmd[i] + 2)) {
1591 case '0':
1592 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
1593 if (temp > 4 || temp < -2) {
1594 BPRINT_E("%s: Incorrect range: %s", __func__, cmd[i]);
1595 return NULL;
1596 }
1597 txpoweroffset[10] |= ((temp << 4) & 0xF0);
1598 i += 2;
1599 break;
1600 case '1':
1601 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
1602 if (temp > 4 || temp < -2) {
1603 BPRINT_E("%s: Incorrect range: %s", __func__, cmd[i]);
1604 return NULL;
1605 }
1606 txpoweroffset[11] |= ((temp << 4) & 0xF0);
1607 i += 2;
1608 break;
1609 case '2':
1610 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
1611 if (temp > 4 || temp < -2) {
1612 BPRINT_E("%s: Incorrect range: %s", __func__, cmd[i]);
1613 return NULL;
1614 }
1615 txpoweroffset[12] |= ((temp << 4) & 0xF0);
1616 i += 2;
1617 break;
1618 case '3':
1619 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
1620 if (temp > 4 || temp < -2) {
1621 BPRINT_E("%s: Incorrect range: %s", __func__, cmd[i]);
1622 return NULL;
1623 }
1624 txpoweroffset[13] |= ((temp << 4) & 0xF0);
1625 i += 2;
1626 break;
1627 case '4':
1628 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
1629 if (temp > 4 || temp < -2) {
1630 BPRINT_E("%s: Incorrect range: %s", __func__, cmd[i]);
1631 return NULL;
1632 }
1633 txpoweroffset[14] |= ((temp << 4) & 0xF0);
1634 i += 2;
1635 break;
1636 case '5':
1637 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
1638 if (temp > 4 || temp < -2) {
1639 BPRINT_E("%s: Incorrect range: %s", __func__, cmd[i]);
1640 return NULL;
1641 }
1642 txpoweroffset[15] |= ((temp << 4) & 0xF0);
1643 i += 2;
1644 break;
1645 default:
1646 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1647 return NULL;
1648 }
1649 break;
1650 case 'i': // lvl 8 offset DPC value
1651 if (pwr16 == true) {
1652 BPRINT_E("%s: Incorrect format: %s - 7668 groups should only 0~5", __func__, cmd[i]);
1653 return NULL;
1654 }
1655 if (cmd_len == 10) {
1656 cmd_len = 22;
1657 txpoweroffset[3] = 0x12;
1658 }
1659 hybrid = true;
1660 switch (*(cmd[i] + 2)) {
1661 case '0':
1662 lvl_8_temp[0] = (char)strtol(cmd[i + 1], NULL, 10);
1663 i += 2;
1664 break;
1665 case '1':
1666 lvl_8_temp[1] = (char)strtol(cmd[i + 1], NULL, 10);
1667 i += 2;
1668 break;
1669 case '2':
1670 lvl_8_temp[2] = (char)strtol(cmd[i + 1], NULL, 10);
1671 i += 2;
1672 break;
1673 case '3':
1674 lvl_8_temp[3] = (char)strtol(cmd[i + 1], NULL, 10);
1675 i += 2;
1676 break;
1677 case '4':
1678 lvl_8_temp[4] = (char)strtol(cmd[i + 1], NULL, 10);
1679 i += 2;
1680 break;
1681 case '5':
1682 lvl_8_temp[5] = (char)strtol(cmd[i + 1], NULL, 10);
1683 i += 2;
1684 break;
1685 default:
1686 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1687 return NULL;
1688 }
1689 break;
1690 case 'e': // ePA offset
1691 if (pwr16 == true) {
1692 BPRINT_E("%s: Incorrect format: %s - 7668 groups should only 0~5", __func__, cmd[i]);
1693 return NULL;
1694 }
1695 if (cmd_len == 10) {
1696 cmd_len = 22;
1697 txpoweroffset[3] = 0x12;
1698 }
1699 hybrid = true;
1700 switch (*(cmd[i] + 2)) {
1701 case '0':
1702 txpoweroffset[16] = strtol(cmd[i + 1], NULL, 10);
1703 i += 2;
1704 break;
1705 case '1':
1706 txpoweroffset[17] = strtol(cmd[i + 1], NULL, 10);
1707 i += 2;
1708 break;
1709 case '2':
1710 txpoweroffset[18] = strtol(cmd[i + 1], NULL, 10);
1711 i += 2;
1712 break;
1713 case '3':
1714 txpoweroffset[19] = strtol(cmd[i + 1], NULL, 10);
1715 i += 2;
1716 break;
1717 case '4':
1718 txpoweroffset[20] = strtol(cmd[i + 1], NULL, 10);
1719 i += 2;
1720 break;
1721 case '5':
1722 txpoweroffset[21] = strtol(cmd[i + 1], NULL, 10);
1723 i += 2;
1724 break;
1725 default:
1726 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1727 return NULL;
1728 }
1729 break;
1730 default:
1731 i++;
1732 }
1733 }
1734 if (pwr16 == true) {
1735 txpoweroffset[3] = 0x10;
1736 cmd_len = txpoweroffset[3] + 4;
1737 BPRINT_I("%s: "BLUE"This is 16 groups setting for 7663, 7921"NONE, __func__);
1738 } else if (lvl_8 == true) {
1739 for (i = 0 ; i < 6 ; i++)
1740 txpoweroffset[i + 10] |= (lvl_8_temp[i] & 0x0F);
1741 hybridmode[4] = 0x02;
1742 } else {
1743 BPRINT_I("%s: "BLUE"This is 6 groups setting for 7662, 7668 etc."NONE, __func__);
1744 for (i = 0 ; i < 6 ; i++)
1745 txpoweroffset[i + 10] = lvl_8_temp[i];
1746 hybridmode[4] = 0x01;
1747 }
1748 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, txpoweroffset, cmd_len , NULL, NULL);
1749 if (hybrid == true) {
1750 list = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, hybridmode, sizeof(hybridmode), node, node);
1751 return list;
1752 }
1753 return node;
1754}
1755
1756//---------------------------------------------------------------------------
1757static pkt_list_s *mtk_boots_cmd_efuse_wr(char *cmd[], size_t len)
1758{
1759 uint8_t efuse_r[] = {0x01, 0x6F, 0xFC, 0x0E,
1760 0x01, 0x0D, 0x0A, 0x00, 0x02, 0x04,
1761 0x00, 0x00, 0x00, 0x00,
1762 0x00, 0x00, 0x00, 0x00};
1763 uint8_t efuse_w[] = {0x01, 0x6F, 0xFC, 0x18,
1764 0x01, 0x0D, 0x14, 0x00, 0x01, 0x01,
1765 0x00, 0x00,
1766 0x00, 0x00, 0x00, 0x00,
1767 0x00, 0x00, 0x00, 0x00,
1768 0x00, 0x00, 0x00, 0x00,
1769 0x00, 0x00, 0x00, 0x00};
1770 pkt_list_s *node = NULL;
1771 uint16_t addr = 0;
1772 size_t i = 1;
1773
1774 BPRINT_D("%s", __func__);
1775 if (len == 2 && *(cmd[1] + 1) == 'h') {
1776 return NULL;
1777 } else if (len % 2) {
1778 BPRINT_E("%s: Incorrect format", __func__);
1779 return NULL;
1780 }
1781 /*
1782 * efuse -w -a <> -v <>
1783 * efuse -r -a <>
1784 */
1785
1786 while (i + 1 < len) {
1787 switch (*(cmd[i] + 1)) {
1788 case 'w':
1789 /* read value first
1790 efuse[3] = 24;
1791 efuse[6] = 0x14;
1792 efuse[8] = 0x01;
1793 efuse[8] = 0x01;
1794 */
1795 efuse_r[3] = 14; /* length */
1796 efuse_r[6] = 0x0A;
1797 efuse_r[8] = 0x02;
1798 efuse_r[9] = 0x04;
1799 efuse_reg_wr.wr_flag = WR_FLAG_WRITE;
1800 i += 1;
1801 break;
1802 case 'r':
1803 efuse_r[3] = 14; /* length */
1804 efuse_r[6] = 0x0A;
1805 efuse_r[8] = 0x02;
1806 efuse_r[9] = 0x04;
1807 efuse_reg_wr.wr_flag = WR_FLAG_READ;
1808 i += 1;
1809 break;
1810 case 'a':
1811 efuse_reg_wr.addr = strtoul(cmd[i + 1], NULL, 16);
1812 addr = efuse_reg_wr.addr / 16 * 4;
1813 efuse_r[10] = addr & 0xFF;
1814 efuse_r[11] = (addr & 0xFF00) >> 8;
1815 efuse_r[12] = (addr + 1) & 0xFF;
1816 efuse_r[13] = ((addr + 1) & 0xFF00) >> 8;
1817 efuse_r[14] = (addr + 2) & 0xFF;
1818 efuse_r[15] = ((addr + 2) & 0xFF00) >> 8;
1819 efuse_r[16] = (addr + 3) & 0xFF;
1820 efuse_r[17] = ((addr + 3) & 0xFF00) >> 8;
1821 i += 2;
1822 break;
1823 case 'v':
1824 efuse_reg_wr.value = strtoul(cmd[i + 1], NULL, 16);
1825 i += 2;
1826 break;
1827
1828 default:
1829 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1830 return NULL;
1831 }
1832 }
1833
1834 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, efuse_r, (efuse_r[3] + 4),
1835 NULL, NULL);
1836 if (efuse_reg_wr.wr_flag == WR_FLAG_WRITE && node)
1837 {
1838 boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, efuse_w, (efuse_w[3] + 4),
1839 node, node);
1840 }
1841 return node;
1842}
1843
1844//---------------------------------------------------------------------------
1845static pkt_list_s *mtk_boots_cmd_register_wr(char *cmd[], size_t len)
1846{
1847 uint8_t reg[] = {0x01, 0x00, 0xFC, 0x00,
1848 0x00, 0x00, 0x00, 0x00,
1849 0x00, 0x00, 0x00, 0x00};
1850 pkt_list_s *node = NULL;
1851 size_t i = 1;
1852
1853 BPRINT_D("%s", __func__);
1854 if (len == 2 && *(cmd[1] + 1) == 'h') {
1855 return NULL;
1856 } else if (len % 2) {
1857 BPRINT_E("%s: Incorrect format", __func__);
1858 return NULL;
1859 }
1860 /*
1861 * register -w -a <> -v <>
1862 * register -r -a <>
1863 */
1864
1865 while (i + 1 < len) {
1866 switch (*(cmd[i] + 1)) {
1867 case 'w':
1868 reg[1] = 0xD0;
1869 reg[3] = 0x08; /* length */
1870 efuse_reg_wr.wr_flag = WR_FLAG_WRITE;
1871 i += 1;
1872 break;
1873 case 'r':
1874 reg[1] = 0xD1;
1875 reg[3] = 0x04; /* length */
1876 efuse_reg_wr.wr_flag = WR_FLAG_READ;
1877 i += 1;
1878 break;
1879 case 'a':
1880 efuse_reg_wr.addr = strtoul(cmd[i + 1], NULL, 16);
1881 reg[4] = efuse_reg_wr.addr & 0xFF;
1882 reg[5] = (efuse_reg_wr.addr & 0xFF00) >> 8;
1883 reg[6] = (efuse_reg_wr.addr & 0xFF0000) >> 16;
1884 reg[7] = (efuse_reg_wr.addr & 0xFF000000) >> 24;
1885 i += 2;
1886 break;
1887 case 'v':
1888 efuse_reg_wr.value = strtoul(cmd[i + 1], NULL, 16);
1889 reg[8] = efuse_reg_wr.value & 0xFF;
1890 reg[9] = (efuse_reg_wr.value & 0xFF00) >> 8;
1891 reg[10] = (efuse_reg_wr.value & 0xFF0000) >> 16;
1892 reg[11] = (efuse_reg_wr.value & 0xFF000000) >> 24;
1893 i += 2;
1894 break;
1895
1896 default:
1897 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1898 return NULL;
1899 }
1900 }
1901
1902 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, reg, (reg[3] + 4),
1903 NULL, NULL);
1904 return node;
1905}
1906
1907//---------------------------------------------------------------------------
1908static pkt_list_s *mtk_boots_cmd_file_wr(char *cmd[], size_t len)
1909{
1910 uint8_t file[256] = {0x01, 0x01, 0xFF, 0x06,
1911 0x00,
1912 0x00, 0x00, 0x00, 0x00,
1913 0x00,
1914 0x00};
1915 uint32_t addr = 0;
1916 uint8_t file_path = 0;
1917 pkt_list_s *node = NULL;
1918 size_t i = 1;
1919
1920 BPRINT_D("%s", __func__);
1921 if (len == 2 && *(cmd[1] + 1) == 'h') {
1922 return NULL;
1923 } else if (len % 2) {
1924 BPRINT_E("%s: Incorrect format", __func__);
1925 return NULL;
1926 }
1927 /****************************************************
1928 format:
1929 CMD: 01 01 FF LEN WR ADDR VALUE FILE_PATH
1930 EVENT: 04 0E LEN 01 01 FF ERRNO WR ADDR VALUE
1931
1932 LEN: 1 byte
1933 WR: 1 byte
1934 ADDR: 4 bytes
1935 VALUE: 1 byte
1936 ERRNO: 2 bytes
1937 FILE_PATH:
1938 ****************************************************/
1939
1940 while (i + 1 < len) {
1941 switch (*(cmd[i] + 1)) {
1942 case 'w':
1943 file[4] = WR_FLAG_WRITE;
1944 i += 1;
1945 break;
1946 case 'r':
1947 file[4] = WR_FLAG_READ;
1948 i += 1;
1949 break;
1950 case 'a':
1951 addr = strtoul(cmd[i + 1], NULL, 16);
1952 file[5] = addr & 0xFF;
1953 file[6] = (addr & 0xFF00) >> 8;
1954 file[7] = (addr & 0xFF0000) >> 16;
1955 file[8] = (addr & 0xFF000000) >> 24;
1956 i += 2;
1957 break;
1958 case 'v':
1959 file[9] = strtol(cmd[i + 1], NULL, 16);
1960 i += 2;
1961 break;
1962 case 'f':
1963 strncpy((char *)&file[10], cmd[i + 1], strlen(cmd[i + 1]) < (256 - 10 - 1) ? strlen(cmd[i + 1]) : (256 - 10 - 1));
1964 file[3] += strlen((char *)&file[10]) + 1;
1965 file_path = 1;
1966 i += 2;
1967 break;
1968 default:
1969 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
1970 return NULL;
1971 }
1972 }
1973
1974 if (file_path == 0)
1975 {
1976 BPRINT_E("%s: please input the file path and name(-f)", __func__);
1977 return NULL;
1978 }
1979
1980 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, file, (file[3] + 4),
1981 NULL, NULL);
1982 return node;
1983}
1984
1985//---------------------------------------------------------------------------
1986static pkt_list_s *mtk_boots_cmd_sync(char *cmd[], size_t len)
1987{
1988 uint8_t access_code[] = {0x01, 0x12, 0xFC, 0x08, 0, 0, 0, 0, 0, 0, 0, 0};
1989 pkt_list_s *node = NULL;
1990
1991 if (len == 2 && *(cmd[1] + 1) == 'h') {
1992 return NULL;
1993 } else if (len >= 2 && strlen(cmd[1]) == 23) {
1994 access_code[11] = strtol(cmd[1], NULL, 16);
1995 access_code[10] = strtol(cmd[1] + 3, NULL, 16);
1996 access_code[9] = strtol(cmd[1] + 6, NULL, 16);
1997 access_code[8] = strtol(cmd[1] + 9, NULL, 16);
1998 access_code[7] = strtol(cmd[1] + 12, NULL, 16);
1999 access_code[6] = strtol(cmd[1] + 15, NULL, 16);
2000 access_code[5] = strtol(cmd[1] + 18, NULL, 16);
2001 access_code[4] = strtol(cmd[1] + 21, NULL, 16);
2002 } else {
2003 BPRINT_E("%s: Incorrect format", __func__);
2004 return NULL;
2005 }
2006
2007 if (!access_code[4] && !access_code[5] && !access_code[6] && !access_code[7]
2008 && !access_code[8] && !access_code[9] && !access_code[10] && !access_code[11]) {
2009 BPRINT_E("%s: Incorrect format", __func__);
2010 return NULL;
2011 }
2012
2013 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, access_code,
2014 sizeof(access_code), NULL, NULL);
2015 return node;
2016}
2017
2018//---------------------------------------------------------------------------
2019static pkt_list_s *mtk_boots_cmd_stress_test(char *cmd[], size_t len)
2020{
2021 uint8_t cmd_buf[BOOTS_STRESS_STRESS_TEST_MAX_PKT_SIZE + HCI_CMD_PKT_HDR_LEN] = {0};
2022 pkt_list_s *node = NULL;
2023 uint32_t packetSize = 1;
2024 uint32_t i;
2025
2026 if (len == 2 && *(cmd[1] + 1) == 'h')
2027 return NULL;
2028
2029 if (len == 2)
2030 packetSize = atoi(cmd[1]);
2031
2032 if (packetSize > BOOTS_STRESS_STRESS_TEST_MAX_PKT_SIZE) {
2033 BPRINT_E("Packet Size should be smaller than %d!", BOOTS_STRESS_STRESS_TEST_MAX_PKT_SIZE);
2034 return NULL;
2035 }
2036
2037 BPRINT_I("%s : Test with 'Write Local Name', Packet Size = %d", __func__, packetSize);
2038 cmd_buf[0] = 0x01;
2039 cmd_buf[1] = 0x13;
2040 cmd_buf[2] = 0x0c;
2041 cmd_buf[3] = packetSize;
2042 for (i = 0; i < packetSize; i++)
2043 cmd_buf[i + HCI_CMD_PKT_HDR_LEN] = ((i + 1) & 0xff);
2044
2045 if (BOOTS_STRESS_MEASURE_IN_BOOTS)
2046 boots_stress_init();
2047
2048 node = boots_pkt_node_push(SCRIPT_STRESS, HCI_CMD_PKT, cmd_buf, packetSize + HCI_CMD_PKT_HDR_LEN, NULL, NULL);
2049 return node;
2050}
2051
2052//---------------------------------------------------------------------------
2053static pkt_list_s *mtk_boots_cmd_loop_back_test(char *cmd[], size_t len)
2054{
2055 uint8_t cmd_reset[] = {0x01, 0x03, 0x0C, 0x00};
2056 uint8_t cmd_loopback[] = {0x01, 0x02, 0x18, 0x01, 0x01};
2057 uint8_t cmd_buf[BOOTS_STRESS_LOOPBACK_TEST_MAX_PKT_SIZE + HCI_ACL_PKT_HDR_LEN] = {0};
2058 pkt_list_s *node = NULL;
2059 pkt_list_s *node_tmp = NULL;
2060 uint32_t packetSize = 1;
2061 uint32_t i;
2062 int32_t wait = 1;
2063
2064 if (len == 2 && *(cmd[1] + 1) == 'h')
2065 return NULL;
2066
2067 if (len == 2)
2068 packetSize = atoi(cmd[1]);
2069
2070 if (packetSize > BOOTS_STRESS_LOOPBACK_TEST_MAX_PKT_SIZE) {
2071 BPRINT_E("Packet Size should be smaller than %d!", BOOTS_STRESS_LOOPBACK_TEST_MAX_PKT_SIZE);
2072 return NULL;
2073 }
2074
2075 BPRINT_I("%s : Test with ACL loopback, Packet Size = %d", __func__, packetSize);
2076 cmd_buf[0] = 0x02;
2077 cmd_buf[1] = 0x32;
2078 cmd_buf[2] = 0x00;
2079 cmd_buf[3] = (packetSize & 0x00ff);
2080 cmd_buf[4] = ((packetSize & 0xff00) >> 8);
2081 for (i = 0; i < packetSize; i++)
2082 cmd_buf[i + HCI_ACL_PKT_HDR_LEN] = ((i + 1) & 0xff);
2083
2084 if (BOOTS_STRESS_MEASURE_IN_BOOTS)
2085 boots_stress_init();
2086
2087 node = boots_pkt_node_push(SCRIPT_CMD, HCI_CMD_PKT, cmd_reset, sizeof(cmd_reset), NULL, NULL);
2088 if (node)
2089 node_tmp = boots_pkt_node_push(SCRIPT_CMD, HCI_CMD_PKT, cmd_loopback, sizeof(cmd_loopback), node, node);
2090 if (node_tmp)
2091 node_tmp = boots_pkt_node_push(SCRIPT_WAITRX, HCI_EVENT_PKT, (void*)&wait, 0, node_tmp, node);
2092 if (node_tmp)
2093 node_tmp = boots_pkt_node_push(SCRIPT_WAITRX, HCI_EVENT_PKT, (void*)&wait, 0, node_tmp, node);
2094 if (node_tmp)
2095 node_tmp = boots_pkt_node_push(SCRIPT_WAITRX, HCI_EVENT_PKT, (void*)&wait, 0, node_tmp, node);
2096 if (node_tmp)
2097 boots_pkt_node_push(SCRIPT_LOOPBACK, HCI_ACL_PKT, cmd_buf, packetSize + HCI_ACL_PKT_HDR_LEN, node_tmp, node);
2098 return node;
2099}
2100
2101//---------------------------------------------------------------------------
2102static pkt_list_s *mtk_boots_cmd_loop_timer_test(char *cmd[], size_t len)
2103{
2104 uint8_t cmd_reset[] = {0x01, 0x03, 0x0C, 0x00};
2105 uint8_t cmd_loopback[] = {0x01, 0x02, 0x18, 0x01, 0x01};
2106 uint8_t cmd_buf[BOOTS_STRESS_LOOPBACK_TEST_MAX_PKT_SIZE + HCI_ACL_PKT_HDR_LEN] = {0};
2107 pkt_list_s *node = NULL;
2108 pkt_list_s *node_tmp = NULL;
2109 uint32_t packetSize = 1;
2110 uint32_t i = 1;
2111 int32_t wait = 1;
2112
2113 if (len == 2 && *(cmd[1] + 1) == 'h') {
2114 return NULL;
2115 } else if (!(len % 2)) {
2116 BPRINT_E("%s: Incorrect format", __func__);
2117 return NULL;
2118 }
2119
2120 boots_loop_timer = 0;
2121
2122 while (i + 1 < len) {
2123 switch (*(cmd[i] + 1)) {
2124 case 't': // timer
2125 boots_loop_timer = atoi(cmd[i + 1]);
2126 i += 2;
2127 break;
2128 case 's': // package size
2129 packetSize = atoi(cmd[i + 1]);
2130 i += 2;
2131 break;
2132 default:
2133 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2134 return NULL;
2135 }
2136 }
2137
2138 if (packetSize > BOOTS_STRESS_LOOPBACK_TEST_MAX_PKT_SIZE) {
2139 BPRINT_E("Packet Size should be smaller than %d!", BOOTS_STRESS_LOOPBACK_TEST_MAX_PKT_SIZE);
2140 return NULL;
2141 }
2142
2143 BPRINT_I("%s : Test with ACL loopback, Timer = %d, Packet Size = %d", __func__, boots_loop_timer, packetSize);
2144 cmd_buf[0] = 0x02;
2145 cmd_buf[1] = 0x32;
2146 cmd_buf[2] = 0x00;
2147 cmd_buf[3] = (packetSize & 0x00ff);
2148 cmd_buf[4] = ((packetSize & 0xff00) >> 8);
2149 for (i = 0; i < packetSize; i++)
2150 cmd_buf[i + HCI_ACL_PKT_HDR_LEN] = ((i + 1) & 0xff);
2151
2152 if (BOOTS_STRESS_MEASURE_IN_BOOTS)
2153 boots_stress_init();
2154
2155 node = boots_pkt_node_push(SCRIPT_CMD, HCI_CMD_PKT, cmd_reset, sizeof(cmd_reset), NULL, NULL);
2156 if (node)
2157 node_tmp = boots_pkt_node_push(SCRIPT_CMD, HCI_CMD_PKT, cmd_loopback, sizeof(cmd_loopback), node, node);
2158 if (node_tmp)
2159 node_tmp = boots_pkt_node_push(SCRIPT_WAITRX, HCI_EVENT_PKT, (void*)&wait, 0, node_tmp, node);
2160 if (node_tmp)
2161 node_tmp = boots_pkt_node_push(SCRIPT_WAITRX, HCI_EVENT_PKT, (void*)&wait, 0, node_tmp, node);
2162 if (node_tmp)
2163 node_tmp = boots_pkt_node_push(SCRIPT_WAITRX, HCI_EVENT_PKT, (void*)&wait, 0, node_tmp, node);
2164 if (node_tmp)
2165 boots_pkt_node_push(SCRIPT_LPTIMER, HCI_ACL_PKT, cmd_buf, packetSize + HCI_ACL_PKT_HDR_LEN, node_tmp, node);
2166 return node;
2167}
2168
2169//---------------------------------------------------------------------------
2170static pkt_list_s *mtk_boots_cmd_set_pa(char *cmd[], size_t len)
2171{
2172 uint8_t epa[] = {0x01, 0x70, 0xFD, 0x09,
2173 0x00, // 00 : Disable ePA, 01 : Enable ePA
2174 0x07, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00 // power Level, same as pwrlvl and radio
2175 };
2176 pkt_list_s *node = NULL;
2177
2178 BPRINT_D("%s", __func__);
2179 if (len == 2 && *(cmd[1] + 1) == 'h') {
2180 return NULL;
2181 } else if (len < 2) {
2182 BPRINT_E("%s: Incorrect format", __func__);
2183 return NULL;
2184 }
2185
2186 epa[4] = strtol(cmd[1], NULL, 16);
2187 if (epa[4] > 1 || (epa[4] == 0 && *cmd[1] != '0')) {
2188 BPRINT_E("%s: Incorrect format: %d", __func__, epa[4]);
2189 return NULL;
2190 }
2191 if (epa[4] == 1) {
2192 BPRINT_D("ePA mode, change power level to level 9.");
2193 epa[5] = 0x09;
2194 epa[9] = 0x09;
2195 epa[10] = 0x09;
2196 }
2197 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, epa, sizeof(epa),
2198 NULL, NULL);
2199 return node;
2200}
2201
2202//---------------------------------------------------------------------------
2203static pkt_list_s *mtk_boots_cmd_set_ant(char *cmd[], size_t len)
2204{
2205 uint8_t ant[] = {0x01, 0x71, 0xFD, 0x01, 0}; //00 : BT uses ANT2,FDD 01 : BT uses ANT1,TDD
2206 pkt_list_s *node = NULL;
2207
2208 BPRINT_D("%s", __func__);
2209 if (len == 2 && *(cmd[1] + 1) == 'h') {
2210 return NULL;
2211 } else if (len < 2) {
2212 BPRINT_E("%s: Incorrect format", __func__);
2213 return NULL;
2214 }
2215
2216 ant[4] = strtol(cmd[1], NULL, 16);
2217 if (ant[4] > 1 || (ant[4] == 0 && *cmd[1] != '0')) {
2218 BPRINT_E("%s: Incorrect format: %d", __func__, ant[4]);
2219 return NULL;
2220 }
2221 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, ant, sizeof(ant),
2222 NULL, NULL);
2223 return node;
2224}
2225
2226//---------------------------------------------------------------------------
2227static pkt_list_s *mtk_boots_cmd_background_rssi_scan(char *cmd[], size_t len)
2228{
2229 uint8_t ant[] = {0x01, 0x73, 0xFD, 0x01, 0}; //00 : disable 01 : enable
2230 pkt_list_s *list = NULL;
2231 pkt_list_s *node = NULL;
2232 rssi_set_s rssi;
2233 uint32_t i = 2;
2234
2235 BPRINT_D("%s", __func__);
2236 if (len == 2 && *(cmd[1] + 1) == 'h') {
2237 return NULL;
2238 } else if (len < 2) {
2239 BPRINT_E("%s: Incorrect format", __func__);
2240 return NULL;
2241 }
2242 ant[4] = strtol(cmd[1], NULL, 16);
2243
2244 rssi.avg_package = 1;
2245 rssi.ch_start = 0;
2246 rssi.ch_end = 78;
2247 rssi.report = false;
2248 rssi.stop = !ant[4];
2249 rssi.alpha_filter = 0;
2250 rssi.one_shot = 0;
2251
2252 if (ant[4] > 1 || (ant[4] == 0 && *cmd[1] != '0')) {
2253 BPRINT_E("%s: Incorrect format", __func__);
2254 return NULL;
2255 }
2256
2257 while (i + 1 < len) {
2258 switch (*(cmd[i] + 1)) {
2259 case 'o': // output report when stop
2260 rssi.report = atoi(cmd[i + 1]);
2261 i += 2;
2262 break;
2263 case 's': // start channel
2264 rssi.ch_start = atoi(cmd[i + 1]);
2265 if (rssi.ch_start < 0 || rssi.ch_start > 78)
2266 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2267 i += 2;
2268 break;
2269 case 'e': // end chennel
2270 rssi.ch_end = atoi(cmd[i + 1]);
2271 if (rssi.ch_end < 0 || rssi.ch_end > 78)
2272 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2273 i += 2;
2274 break;
2275 case 'a': // average package
2276 rssi.avg_package = atoi(cmd[i + 1]);
2277 i += 2;
2278 break;
2279 case 'f': // alpha filter
2280 rssi.alpha_filter = atoi(cmd[i + 1]);
2281 i += 2;
2282 break;
2283 case 'n': // report only one
2284 rssi.one_shot = atoi(cmd[i + 1]);
2285 i += 2;
2286 break;
2287 default:
2288 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2289 return NULL;
2290 }
2291 }
2292
2293 if (rssi.ch_end < rssi.ch_start)
2294 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2295
2296 node = boots_pkt_node_push(SCRIPT_RSSI, HCI_CMD_PKT, &rssi, sizeof(rssi), NULL, NULL);
2297 list = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, ant, sizeof(ant), node, node);
2298
2299 return list;
2300}
2301
2302//---------------------------------------------------------------------------
2303static pkt_list_s *mtk_boots_cmd_packet_rssi(char *cmd[], size_t len)
2304{
2305 uint8_t rssi[] = {0x01, 0x61, 0xFC, 0x02, 0x32, 0x00};
2306 pkt_list_s *node = NULL;
2307 uint16_t handle = 0;
2308 uint32_t i = 1;
2309
2310 BPRINT_D("%s", __func__);
2311 if (len == 2 && *(cmd[1] + 1) == 'h') {
2312 return NULL;
2313 }
2314
2315 while (i + 1 < len) {
2316 switch (*(cmd[i] + 1)) {
2317 case 'a': // handle, default 0x0032, opt.
2318 handle = (uint16_t)strtoul(cmd[i + 1], NULL, 16);
2319 rssi[4] = (uint8_t)(handle & 0x00FF);
2320 rssi[5] = (uint8_t)((handle & 0xFF00) >> 8);
2321 i += 2;
2322 break;
2323 default:
2324 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2325 return NULL;
2326 }
2327 }
2328
2329 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, &rssi, sizeof(rssi), NULL, NULL);
2330 return node;
2331}
2332
2333//---------------------------------------------------------------------------
2334static pkt_list_s *mtk_boots_cmd_set_buffer_mode(char *cmd[], size_t len)
2335{
2336 FILE *fp = NULL;
2337 ssize_t read = 0;
2338 size_t line_len = 0;
2339 char *wbuf = NULL;
2340 char *line = NULL;
2341 int fp_len = 0;
2342 char path[64] = DEFAULT_WIFI_CFG;
2343 char path_cp[64] = DEFAULT_WIFI_CFG;
2344 size_t i = 1;
2345 ssize_t w_size = 0;
2346 int enable = 0;
2347 char *pch = NULL;
2348 char str_buf[64];
2349
2350 BPRINT_D("%s", __func__);
2351 if (len == 2 && *(cmd[1] + 1) == 'h') {
2352 return NULL;
2353 }
2354
2355 while (i + 1 < len) {
2356 switch (*(cmd[i] + 1)) {
2357 case 'f':
2358 memset(path, 0x00, sizeof(path));
2359 strncpy(path, cmd[i + 1], sizeof(path) - 1);
2360 strncpy(path_cp, cmd[i + 1], sizeof(path_cp) - 1);
2361 i += 2;
2362 break;
2363 case 'e':
2364 enable = atoi(cmd[i + 1]);
2365 i += 2;
2366 break;
2367 default:
2368 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2369 return NULL;
2370 }
2371 }
2372
2373 fp = fopen(path, "r+");
2374 if (fp != NULL) {
2375 fseek(fp, 0L, SEEK_END);
2376 fp_len = ftell(fp);
2377 wbuf = malloc(fp_len + 1 + 21);
2378 if (!wbuf) {
2379 BPRINT_E("%s: Alloc wbuf failed", __func__);
2380 fclose(fp);
2381 return NULL;
2382 }
2383 fseek(fp, 0L, SEEK_SET);
2384
2385 while ((read = getline(&line, &line_len, fp)) != -1) {
2386 pch = strstr(line, E2P_MODE);
2387 if (!pch) {
2388 memcpy(&wbuf[w_size], line, read);
2389 w_size += read;
2390 } else
2391 continue;
2392 }
2393 free(line);
2394 fclose(fp);
2395 } else {
2396 wbuf = malloc(21);
2397 if (!wbuf) {
2398 BPRINT_E("%s: Alloc wbuf failed", __func__);
2399 return NULL;
2400 }
2401 }
2402
2403 i = snprintf(str_buf, sizeof(str_buf),"%s %d\n", E2P_MODE, enable);
2404 memcpy(&wbuf[w_size], str_buf, i);
2405 w_size += i;
2406 fp = fopen(path_cp, "w");
2407 if (fp == NULL) {
2408 BPRINT_E("open file %s failed, errno = %s(%d)\n", path_cp, strerror(errno), errno);
2409 free(wbuf);
2410 return NULL;
2411 }
2412 fwrite(wbuf, 1, w_size, fp);
2413 fclose(fp);
2414 free(wbuf);
2415 // Please note driver also need support this after ...[TODO]
2416 boots_write_stpbtfwlog("reload_setting");
2417 BPRINT_I("Set %s:%d, if no efficacy please reboot platform.", E2P_MODE, enable);
2418 return NULL;
2419}
2420
2421//---------------------------------------------------------------------------
2422static pkt_list_s *mtk_boots_cmd_set_tx_hopping(char *cmd[], size_t len)
2423{
2424 uint8_t tx_hopping[] = {0x01, 0x90, 0xFD, 0x01, 0x00};
2425 pkt_list_s *node = NULL;
2426
2427 BPRINT_D("%s", __func__);
2428 if (len != 2) {
2429 BPRINT_E("%s: Incorrect format", __func__);
2430 return NULL;
2431 }
2432
2433 if (!memcmp("low", cmd[1], strlen("low"))) {
2434 tx_hopping[4] = 0x00;
2435 } else if (!memcmp("middle", cmd[1], strlen("middle"))) {
2436 tx_hopping[4] = 0x01;
2437 } else if (!memcmp("high", cmd[1], strlen("high"))) {
2438 tx_hopping[4] = 0x02;
2439 } else {
2440 BPRINT_E("%s: Incorrect format: %s)", __func__, cmd[1]);
2441 return NULL;
2442 }
2443
2444 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, tx_hopping,
2445 sizeof(tx_hopping), NULL, NULL);
2446 return node;
2447}
2448
2449//---------------------------------------------------------------------------
2450static pkt_list_s *mtk_boots_cmd_switch_bt(char *cmd[], size_t len)
2451{
2452 uint8_t switch_bt[] = {0x01, 0xF4, 0xFC, 0x02, 0xFD, 0}; // 0 : BT0 1 : BT1
2453 pkt_list_s *node = NULL;
2454
2455 BPRINT_D("%s", __func__);
2456 if (len == 2 && *(cmd[1] + 1) == 'h') {
2457 return NULL;
2458 } else if (len < 2) {
2459 BPRINT_E("%s: Incorrect format", __func__);
2460 return NULL;
2461 }
2462
2463 switch_bt[5] = strtoul(cmd[1], NULL, 16);
2464
2465 if (switch_bt[5] > 1 || switch_bt[5] < 0) {
2466 BPRINT_E("%s: Incorrect format: %d)", __func__, switch_bt[5]);
2467 return NULL;
2468 }
2469 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, switch_bt, sizeof(switch_bt),
2470 NULL, NULL);
2471 return node;
2472}
2473
2474//---------------------------------------------------------------------------
2475static pkt_list_s *mtk_boots_cmd_power_compensation(char *cmd[], size_t len)
2476{
2477 uint8_t power_comp[] = {0x01, 0xEA, 0xFC, 0x0A, 0x02, 0x0A,
2478 0, // ANT index
2479 0, // offset level
2480 0, 0, 0, 0, 0, 0}; // group value
2481 pkt_list_s *node = NULL;
2482 size_t i = 1;
2483 int8_t temp = 0x00;
2484
2485 BPRINT_D("%s", __func__);
2486 if (len == 2 && *(cmd[1] + 1) == 'h') {
2487 return NULL;
2488 } else if (!(len % 2)) {
2489 BPRINT_E("%s: Incorrect format", __func__);
2490 return NULL;
2491 }
2492
2493 while (i + 1 < len) {
2494 switch (*(cmd[i] + 1)) {
2495 case 'a': // ANT index
2496 power_comp[6] = strtoul(cmd[i + 1], NULL, 10);
2497 i += 2;
2498 break;
2499 case 'l': // offset level
2500 power_comp[7] = strtoul(cmd[i + 1], NULL, 10);
2501 i += 2;
2502 break;
2503 case 'g': { // group value
2504 uint8_t gpidx = strtoul(cmd[i] + 2, NULL, 10);
2505 if (gpidx > 5 || gpidx < 0) {
2506 BPRINT_E("%s: Incorrect format: %d", __func__, gpidx);
2507 return NULL;
2508 }
2509 temp = (int8_t)strtol(cmd[i + 1], NULL, 10);
2510 if (temp > 16 || temp < -16) {
2511 BPRINT_E("%s: Incorrect range: %s %d", __func__, cmd[i], temp);
2512 return NULL;
2513 }
2514 power_comp[gpidx + 8] = temp;
2515 i += 2;
2516 }
2517 break;
2518 default:
2519 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2520 return NULL;
2521 }
2522 }
2523
2524 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, power_comp, sizeof(power_comp),
2525 NULL, NULL);
2526 return node;
2527}
2528
2529//---------------------------------------------------------------------------
2530static pkt_list_s *mtk_boots_cmd_power_boundary(char *cmd[], size_t len)
2531{
2532 uint8_t power_bdry[] = {0x01, 0xEA, 0xFC, 0x09, 0x02, 0x0B,
2533 0, // ANT index
2534 0, // reserve
2535 0, 0, 0, 0, 0}; // group channel boundry
2536 pkt_list_s *node = NULL;
2537 size_t i = 1;
2538
2539 BPRINT_D("%s", __func__);
2540 if (len == 2 && *(cmd[1] + 1) == 'h') {
2541 return NULL;
2542 } else if (!(len % 2)) {
2543 BPRINT_E("%s: Incorrect format", __func__);
2544 return NULL;
2545 }
2546
2547 while (i + 1 < len) {
2548 switch (*(cmd[i] + 1)) {
2549 case 'a': // ANT index
2550 power_bdry[6] = strtol(cmd[i + 1], NULL, 10);
2551 i += 2;
2552 break;
2553 case 'b': { // boundary value
2554 uint8_t bdidx = strtol(cmd[i] + 2, NULL, 10);
2555 if (bdidx > 4 || bdidx < 0) {
2556 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2557 return NULL;
2558 }
2559 power_bdry[bdidx + 8] = strtol(cmd[i + 1], NULL, 10);
2560 i += 2;
2561 } break;
2562 default:
2563 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2564 return NULL;
2565 }
2566 }
2567
2568 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, power_bdry, sizeof(power_bdry),
2569 NULL, NULL);
2570 return node;
2571}
2572
2573//---------------------------------------------------------------------------
2574static pkt_list_s *mtk_boots_cmd_set_sx(char *cmd[], size_t len)
2575{
2576 uint8_t sxtrx[] = {0x01, 0xEA, 0xFC, 0x03, 0x02,
2577 0, // 0x06 : st_tx 0x07 : st_rx
2578 0}; // as below
2579 /*
2580 BT0 SX Configration 0x15[3:0]
2581 4'b0001:DIV2 for Rx
2582 4'b0011:SSB 8/3 for T/Rx
2583 4'b0100:SSB 16/5 for T/Rx
2584 4'b0101:DIV2 LP for Rx
2585 BT1 SX Configration 0x15[3:0]
2586 4'b0000:VCDL 5/2 for T/Rx
2587 4'b0001:DIV2 for Rx
2588 4'b0010:VCDL 7/2 for T/Rx
2589 4'b0101:DIV2 LP for Rx
2590 */
2591 pkt_list_s *node = NULL;
2592
2593 BPRINT_D("%s", __func__);
2594 if (len == 2 && *(cmd[1] + 1) == 'h') {
2595 return NULL;
2596 } else if (len < 2) {
2597 BPRINT_E("%s: Incorrect format", __func__);
2598 return NULL;
2599 }
2600
2601 if (!memcmp("sxtx", cmd[0], strlen("sxtx"))) {
2602 sxtrx[5] = 0x06;
2603 }
2604
2605 if (!memcmp("sxrx", cmd[0], strlen("sxrx")) ||
2606 !memcmp("swrxmode", cmd[0], strlen("swrxmode"))) {
2607 sxtrx[5] = 0x07;
2608 }
2609
2610 sxtrx[6] = strtol(cmd[1], NULL, 10);
2611
2612 if (sxtrx[6] > 5 || sxtrx[6] < 0) {
2613 BPRINT_E("%s: Incorrect format: %d", __func__, sxtrx[6]);
2614 return NULL;
2615 }
2616 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, sxtrx, sizeof(sxtrx),
2617 NULL, NULL);
2618 return node;
2619}
2620
2621//---------------------------------------------------------------------------
2622static pkt_list_s *mtk_boots_cmd_ant_to_pin_loss(char *cmd[], size_t len)
2623{
2624 uint8_t a2ploss[] = {0x01, 0xEA, 0xFC, 0x03, 0x02, 0x09, 0};
2625 pkt_list_s *node = NULL;
2626
2627 BPRINT_D("%s", __func__);
2628 if (len == 2 && *(cmd[1] + 1) == 'h') {
2629 return NULL;
2630 } else if (len < 2) {
2631 BPRINT_E("%s: Incorrect format", __func__);
2632 return NULL;
2633 }
2634
2635 a2ploss[6] = strtol(cmd[1], NULL, 10);
2636
2637 if (a2ploss[6] > 20 || a2ploss[6] < 0) {
2638 BPRINT_E("%s: Incorrect format: %d", __func__, a2ploss[6]);
2639 return NULL;
2640 }
2641 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, a2ploss, sizeof(a2ploss),
2642 NULL, NULL);
2643 return node;
2644}
2645
2646//---------------------------------------------------------------------------
2647static pkt_list_s *mtk_boots_cmd_read_edr_info(char *cmd[], size_t len)
2648{
2649 uint8_t redrinfo[] = {0x01, 0xEA, 0xFC, 0x03, 0x02, 0x08, 0x00};
2650 pkt_list_s *node = NULL;
2651
2652 BPRINT_D("%s", __func__);
2653 if (len == 2 && *(cmd[1] + 1) == 'h')
2654 return NULL;
2655
2656 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, redrinfo, sizeof(redrinfo),
2657 NULL, NULL);
2658 return node;
2659}
2660
2661//---------------------------------------------------------------------------
2662static pkt_list_s *mtk_boots_cmd_epa_elna(char *cmd[], size_t len)
2663{
2664 uint8_t palna[] = {0x01, 0x97, 0xFC, 0x03, 0x02, 0x02, 0};
2665 pkt_list_s *node = NULL;
2666 size_t i = 1;
2667
2668 BPRINT_D("%s", __func__);
2669 if (len == 2 && *(cmd[1] + 1) == 'h') {
2670 return NULL;
2671 } else if (len < 2) {
2672 BPRINT_E("%s: Incorrect format", __func__);
2673 return NULL;
2674 }
2675
2676 while (i + 1 < len) {
2677 switch (*(cmd[i] + 1)) {
2678 case 'p': // epa
2679 palna[6] |= strtol(cmd[i + 1], NULL, 16);
2680 i += 2;
2681 break;
2682 case 'l': // elna
2683 palna[6] |= strtol(cmd[i + 1], NULL, 16) << 4;
2684 i += 2;
2685 break;
2686
2687 default:
2688 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2689 return NULL;
2690 }
2691 }
2692
2693 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, palna, sizeof(palna),
2694 NULL, NULL);
2695 return node;
2696}
2697
2698//---------------------------------------------------------------------------
2699static pkt_list_s *mtk_boots_cmd_set_xomode(char *cmd[], size_t len)
2700{
2701 uint8_t set_xomode[] = {0x01, 0xEA, 0xFC, 0x02, 0x04, 0}; // 0 : AX mode 1 :BT mode
2702 pkt_list_s *node = NULL;
2703
2704 BPRINT_D("%s", __func__);
2705 if (len == 2 && *(cmd[1] + 1) == 'h') {
2706 return NULL;
2707 } else if (len < 2) {
2708 BPRINT_E("%s: Incorrect format", __func__);
2709 return NULL;
2710 }
2711
2712 set_xomode[5] = strtoul(cmd[1], NULL, 16);
2713
2714 if (set_xomode[5] > 1 || set_xomode[5] < 0) {
2715 BPRINT_E("%s: Incorrect format: %d)", __func__, set_xomode[5]);
2716 return NULL;
2717 }
2718 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, set_xomode, sizeof(set_xomode),
2719 NULL, NULL);
2720 return node;
2721}
2722
2723//---------------------------------------------------------------------------
2724static pkt_list_s *mtk_boots_cmd_get_xomode(char *cmd[], size_t len)
2725{
2726 uint8_t get_xomode[] = {0x01, 0xEA, 0xFC, 0x01, 0x03};
2727 pkt_list_s *node = NULL;
2728
2729 BPRINT_D("%s", __func__);
2730 if (len == 2 && *(cmd[1] + 1) == 'h')
2731 return NULL;
2732
2733 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, get_xomode, sizeof(get_xomode),
2734 NULL, NULL);
2735 return node;
2736}
2737
2738//---------------------------------------------------------------------------
2739static pkt_list_s *mtk_boots_cmd_bt_xo_trim(char *cmd[], size_t len)
2740{
2741 uint8_t xo_trim[] = {0x01, 0xEA, 0xFC, 0x07, 0x06,
2742 0, // Frequency offset ( XO_C1_SEL_BTM)
2743 0, // XO trim2 compensation (XO_C1_SEL_BTM)
2744 0, // XO trim3 compensation (XO_C1_SEL_BTM)
2745 0, // XO trim4 compensation (XO_C1_SEL_BTM)
2746 0x81, // C2 ratio (default 0x81, don’t change)
2747 0x05}; // C1 ratio (default 0x05 , don’t change)
2748 pkt_list_s *node = NULL;
2749 size_t i = 1;
2750 int tmp_val = 0;
2751
2752 BPRINT_D("%s", __func__);
2753 if (len == 2 && *(cmd[1] + 1) == 'h') {
2754 return NULL;
2755 } else if (!(len % 2)) {
2756 BPRINT_E("%s: Incorrect format", __func__);
2757 return NULL;
2758 }
2759
2760 /*
2761 xo_trim[] = 01 EA FC 07 06 UU VV WW XX YY ZZ
2762 UU: [eFuse 0x400] : Frequency offset ( XO_C1_SEL_BTM)
2763 BIT[7] : C1 BTM valid bit
2764 BIT[6:0] : C1 BTM value
2765 VV: [eFuse 0x406] : XO trim2 compensation (XO_C1_SEL_BTM)
2766 BIT[7] : C1 BTM COMP enable bit
2767 BIT[6] : 0: increase bit; 1 : decrease bit
2768 BIT[5:0] : C1 BTM trim2 value
2769 WW: [eFuse 0x40C] : XO trim3 compensation (XO_C1_SEL_BTM)
2770 BIT[7] : C1 BTM COMP enable bit
2771 BIT[6] : 0: increase bit; 1 : decrease bit
2772 BIT[5:0] : C1 BTM trim3 value
2773 XX: [eFuse 0x412] : XO trim4 compensation (XO_C1_SEL_BTM)
2774 BIT[7] : C1 BTM COMP enable bit
2775 BIT[6] : 0: increase bit; 1 : decrease bit
2776 BIT[5:0] : C1 BTM trim4 value
2777 YY: [eFuse 0x403] : C2 ratio (default 0x81, don’t change)
2778 BIT[7] : enable bit
2779 BIT[6:0] : C2 ratio
2780 ZZ: [eFuse 0x409] : C1 ratio (default 0x05 , don’t change)
2781 BIT[7:0] : C1 ratio
2782 For example, C1 ratio and C2 ratio is 5 and 1, and C1 value is 10, C2 is 10 * (1/5) = 2
2783 */
2784
2785 while (i + 1 < len) {
2786 switch (*(cmd[i] + 1)) {
2787 case 'f':
2788 tmp_val = strtol(cmd[i + 1], NULL, 10);
2789 if (tmp_val > 127 || tmp_val < 0) {
2790 BPRINT_E("%s: Incorrect format: -f %s", __func__, cmd[i + 1]);
2791 return NULL;
2792 }
2793 xo_trim[5] = tmp_val | (1 << 7); // enable bit
2794 i += 2;
2795 break;
2796 case 'x':
2797 tmp_val = strtol(cmd[i + 1], NULL, 10);
2798 if (tmp_val > 63 || tmp_val < -63) {
2799 BPRINT_E("%s: Incorrect format: -x %s", __func__, cmd[i + 1]);
2800 return NULL;
2801 }
2802 if (tmp_val == 0) {
2803 xo_trim[6] = tmp_val;
2804 } else if (tmp_val < 0) {
2805 tmp_val = tmp_val * (-1);
2806 xo_trim[6] = tmp_val | (1 << 7); // enable bit
2807 xo_trim[6] = xo_trim[6] | (1 << 6); // increase/decrease bit
2808 } else {
2809 xo_trim[6] = tmp_val | (1 << 7); // enable bit
2810 }
2811 i += 2;
2812 break;
2813 case 'y':
2814 tmp_val = strtol(cmd[i + 1], NULL, 10);
2815 if (tmp_val > 63 || tmp_val < -63) {
2816 BPRINT_E("%s: Incorrect format: -y %s", __func__, cmd[i + 1]);
2817 return NULL;
2818 }
2819 if (tmp_val == 0) {
2820 xo_trim[7] = tmp_val;
2821 } else if (tmp_val < 0) {
2822 tmp_val = tmp_val * (-1);
2823 xo_trim[7] = tmp_val | (1 << 7); // enable bit
2824 xo_trim[7] = xo_trim[7] | (1 << 6); // increase/decrease bit
2825 } else {
2826 xo_trim[7] = tmp_val | (1 << 7); // enable bit
2827 }
2828 i += 2;
2829 break;
2830 case 'z':
2831 tmp_val = strtol(cmd[i + 1], NULL, 10);
2832 if (tmp_val > 63 || tmp_val < -63) {
2833 BPRINT_E("%s: Incorrect format: -z %s", __func__, cmd[i + 1]);
2834 return NULL;
2835 }
2836 if (tmp_val == 0) {
2837 xo_trim[8] = tmp_val;
2838 } else if (tmp_val < 0) {
2839 tmp_val = tmp_val * (-1);
2840 xo_trim[8] = tmp_val | (1 << 7); // enable bit
2841 xo_trim[8] = xo_trim[8] | (1 << 6); // increase/decrease bit
2842 } else {
2843 xo_trim[8] = tmp_val | (1 << 7); // enable bit
2844 }
2845 i += 2;
2846 break;
2847 default:
2848 BPRINT_E("%s: Incorrect format: %s", __func__, cmd[i]);
2849 return NULL;
2850 }
2851 }
2852
2853 node = boots_pkt_node_push(SCRIPT_NONE, HCI_CMD_PKT, xo_trim, sizeof(xo_trim),
2854 NULL, NULL);
2855 return node;
2856}
2857
2858//---------------------------------------------------------------------------
2859#define USAGE_RESET_DETAILS \
2860 " EX: # ./boots -c reset"
2861#define USAGE_INQ_DETAILS \
2862 " EX: # ./boots -c inq -t 5"
2863#define USAGE_DUT_DETAILS \
2864 " EX: # ./boots -c dut"
2865#define USAGE_RADDR_DETAILS \
2866 " EX: # ./boots -c raddr"
2867#define USAGE_WADDR_DETAILS \
2868 " NAP-UAP-LAP\n" \
2869 " EX: # ./boots -c waddr 0E:8D:76:68:00:01"
2870#define USAGE_PWRL_DETAILS \
2871 " EX: # ./boots -c pwrlvl 7"
2872#define USAGE_RFTX_PREFACE \
2873 "RF TX test [-p <XX>] [-c <0-78>] [-t <XX>] [-l <DEC>] [-o <DEC>]"
2874#define USAGE_RFTX_DETAILS \
2875 " [p] Pattern:\n" \
2876 " 01:0000 02:1111\n" \
2877 " 03:1010 04:Pseudo Random Bit Sequence 9(Default)\n" \
2878 " 09:11110000 0A:Tx single tone\n" \
2879 " [c] Channel: 0-78, hopping if ignore this\n" \
2880 " [t] Packet Type:\n" \
2881 " 00:NULL 01:POLL 02:FHS 03:DM1 04:DH1 05:HV1 06:HV2 07:HV3\n" \
2882 " 08:DV 09:AUX 0A:DM3 0B:DH3 0E:DM5 0F:DH5 17:EV3 1C:EV4\n" \
2883 " 1D:EV5 24:2DH1 28:3DH1 2A:2DH3 2B:3DH3 2E:2DH5 2F:3DH5 36:2EV3\n" \
2884 " 37:3EV3 3C:2EV5 3D:3EV5\n" \
2885 " [l] Length: Decimal value., If ignore this boots will use the default value\n" \
2886 " [o] Poll Period: Decimal value. Unit: 1.25ms. If ignore this boots will use the default value\n" \
2887 " NOTE: For other parameters command order is Whiten -> RFTX -> Sync -> PowerLvl\n" \
2888 " EX: # ./boots -c rft -p A -c 78 -t 3D"
2889#define USAGE_RFRX_PREFACE \
2890 "RF RX test start [-p <XX>] [-c <0-78>] [-t <XX>] [-a <XX:XX:XX:XX>]"
2891#define USAGE_RF_STOP_PREFACE \
2892 "RF TX/RX test stop(Except SignalTone \"rft -p a ...\", for that need \"reset\" to stop)"
2893#define USAGE_RF_STOP_DETAILS \
2894 " EX: # ./boots -c rf_stop"
2895#define USAGE_RFRX_STOP_PREFACE \
2896 "RF RX test stop [-p <XX>] [-c <0-78>] [-t <XX>] [-a <XX:XX:XX:XX>]"
2897#define USAGE_RFRX_RESULT_PREFACE \
2898 "RF RX test result [-p <XX>] [-c <0-78>] [-t <XX>] [-a <XX:XX:XX:XX>]"
2899#define USAGE_RFRX_DETAILS \
2900 " [p] Pattern:\n" \
2901 " 01:0000 02:1111\n" \
2902 " 03:1010 04:Pseudo Random Bit Sequence 9(Default)\n" \
2903 " 09:11110000\n" \
2904 " [c] Channel: 0-78\n" \
2905 " [t] Packet Type:\n" \
2906 " 03:DM1 04:DH1 0A:DM3 0B:DH3 0E:DM5 0F:DH5\n" \
2907 " 24:2DH1 28:3DH1 2A:2DH3 2B:3DH3 2E:2DH5 2F:3DH5\n" \
2908 " [a] Tester Address: UAP:LAP1:LAP2:LAP3(Default: 0x00A5F0C3 if ignore it)\n"
2909#define RFR_EX \
2910 " EX: # ./boots -c rfr -p 9 -c 78 -t 2F"
2911#define RFR_S_EX \
2912 " EX: # ./boots -c rfr_stop -p 9 -c 78 -t 2F"
2913#define RFR_R_EX \
2914 " EX: # ./boots -c rfr_result -p 9 -c 78 -t 2F"
2915#define USAGE_BLETX_PREFACE \
2916 "BLE TX test [-c <0-39>] [-l <0-255>] [-p <0-7>]"
2917#define USAGE_BLETX_DETAILS \
2918BLUE" Can replace this by ble_etx, EX: \"ble_etx -y 1 ...\"\n"NONE \
2919 " [c] Channel: 0-39\n" \
2920 " [l] Length in bytes of packet: 0-255(DEC, Default is 37 if ignore this)\n" \
2921 " [p] Pattern:\n" \
2922 " 0:PRBS9 1:11110000 2:10101010 3:PRBS15\n" \
2923 " 4:11111111 5:00000000 6:00001111 7:01010101\n" \
2924 " EX: # ./boots -c ble_tx -c 39 -p 2"
2925#define USAGE_BLERX_DETAILS \
2926 " EX: # ./boots -c ble_rx -c 39"
2927#define USAGE_BLEETX_PREFACE \
2928 "BLE Enhanced TX test [-c <0-39>] [-l <0-255>] [-p <0-7>] [-y <1-4>]"
2929#define USAGE_BLEETX_DETAILS \
2930 " [c] Channel: 0-39\n" \
2931 " [l] Length in bytes of packet: 0-255(DEC)\n" \
2932 " [p] Payload of packet:\n" \
2933 " 0:PRBS9 1:11110000 2:10101010 3:PRBS15\n" \
2934 " 4:11111111 5:00000000 6:00001111 7:01010101\n" \
2935 " [y] Phy:\n" \
2936 " 1:LE 1M 2:LE 2M 3:LE Coded(S=8) 4:LE Coded(S=2)\n" \
2937 " MT7668 only supports LE-1M and LE-2M\n" \
2938 " EX: # ./boots -c ble_etx -c 39 -l 255 -p 7 -y 2"
2939#define USAGE_BLEERX_PREFACE \
2940 "BLE Enhanced RX test [-c <0-39>] [-y <1-3>] [-m <0-1>]"
2941#define USAGE_BLEERX_DETAILS \
2942 " [c] Channel: 0-39\n" \
2943 " [y] Phy: 1:LE 1M 2:LE 2M 3: LE Coded \n" \
2944 " LE Coded MT7668/6632 not support\n" \
2945 " [m] Modulation: 0:Standard 1:Stable\n" \
2946 " EX: # ./boots -c ble_erx -c 39 -y 2 -m 0"
2947#define USAGE_BLE_S_DETAILS \
2948 " EX: # ./boots -c ble_stop"
2949#define USAGE_TXTONE_PREFACE \
2950 "TX tone test(before BLE5.0) [-t <0-4>] [-c <0-78>] [-m <0/1>] [-d <0-2>] [-p <0/1>]\n" \
2951 " (after BLE5.0) [-t <0-4>] [-c <0-78>] [-d <0-6>] [-p <0/1>]"
2952#define USAGE_TXTONE_DETAILS \
2953 RED" before BLE5.0 please following define\n"NONE \
2954 " [t] Tone Type:\n" \
2955 " 0:SingleTone_DC 1:SingleTone_250K 2:SignleTone_400K\n" \
2956 " 3:SignleTone_1M 4:ModulationTone\n" \
2957 " [c] Channel: 0-78\n" \
2958 " The following parameters only for Modulation Tone\n" \
2959 " [m] Mode: 0:BT 1:BLE\n" \
2960 " [d] Modulation(Only for BT mode): 0:1M 1:2M 2:3M\n" \
2961 " [p] Pattern: 0:PRBS9 1:PRBS15\n" \
2962 " EX: # ./boots -c txtone -t 4 -c 78 -m 0 -d 0 -p 1\n" \
2963 RED" after BLE5.0 please following define\n"NONE \
2964 " [t] Tone Type:\n" \
2965 " 0:SingleTone_DC 1:SingleTone_250K 2:SignleTone_400K\n" \
2966 " 3:SignleTone_1M 4:ModulationTone\n" \
2967 " [c] Channel: 0-78\n" \
2968 " The following parameters only for Modulation Tone\n" \
2969 " [d] Modulation: 0:BT EDR 1M 1:BT EDR 2M 2:BT EDR 3M\n" \
2970 " 3:BLE 1M 4:BLE 2M 5:BLR 125K 6:BLR 500K \n" \
2971 " [p] Pattern: 0:PRBS9 1:PRBS15\n" \
2972 " EX: # ./boots -c txtone -t 4 -c 78 -d 3 -p 1"
2973
2974#define USAGE_RADIOSETTING_PREFACE \
2975 "Radio setting"RED"(in level for 7663/7668 only)"NONE" [-b <0~7>] [-e <0~7>] [-m <0~7>] [-s <0~3>] [-o <0/1>]"
2976#define USAGE_RADIOSETTING_DETAILS \
2977 " [b] BT TX power level\n" \
2978 " [e] BLE TX power level\n" \
2979 " [m] Max TX power level\n" \
2980 " [s] use for 1db adjust\n" \
2981 " [o] 0 - Default 3db diff, 1 - 0db diff mode to BR/EDR\n" \
2982 " EX: # ./boots -c radio -b 7 -e 7 -m 7 -s 3 -o 0\n"
2983#define USAGE_TXPOWSETTING_PREFACE \
2984 "Tx power setting"RED"(in dbm for 7921 only)"NONE" [-b <-32~12>] [-e <-29~20>] [-m <-32~12>] [-n <0/1>] [-o <0/1>]"
2985#define USAGE_TXPOWSETTING_DETAILS \
2986 " for Buzzard below\n" \
2987 " [b] EDR init TX power dbm\n" \
2988 " [e] BLE TX power dbm\n" \
2989 " [m] EDR Max TX power dbm\n" \
2990 " [n] 0 - Default disable Lv9, 1 - enable Lv9\n" \
2991 " [o] 0 - Default 3db diff, 1 - 0db diff mode to BR/EDR\n" \
2992 " EX: # ./boots -c txpow -b 10 -e 10 -m 10 -n 1 -o 0"
2993#define USAGE_TXPOWEROFFSET_PREFACE \
2994 "TX power offset\n" \
2995 " 7662/7668(6 groups)., 7663/7921(16 groups):\n" \
2996 " [g16]\n" \
2997 " [-g0 <-16~16>] [-g1 <-16~16>] [-g2 <-16~16>] [-g3 <-16~16>] [-g4 <-16~16>] [-g5 <-16~16>] ...\n" \
2998 " The following ONLY for 7668\n" \
2999 " [-r0 <-2~4>] [-r1 <-2~4>] [-r2 <-2~4>] [-r3 <-2~4>] [-r4 <-2~4>] [-r5 <-2~4>]\n" \
3000 " [-i0 <-6~6> or <-16~8>] [-i1 <-6~6> or <-16~8>] [-i2 <-6~6> or <-16~8>]\n" \
3001 " [-i3 <-6~6> or <-16~8>] [-i4 <-6~6> or <-16~8>] [-i5 <-6~6> or <-16~8>]\n" \
3002 " [-e0 <-16~8>] [-e1 <-16~8>] [-e2 <-16~8>] [-e3 <-16~8>] [-e4 <-16~8>] [-e5 <-16~8>]"
3003#define USAGE_TXPOWEROFFSET_DETAILS \
3004 "\n [g16]: Force setting 16 groups, ONLY for 7663/7921\n" \
3005 " [g] GroupX: 7662/7668 have 6 groups, 7663 have 16 groups\n" \
3006 " 7668 group\n" \
3007 " Group0: CH0 - 12 Group1: CH13 - 25 Group2: CH26 - 38\n" \
3008 " Group3: CH39 - 51 Group4: CH52 - 64 Group5: CH65 - 78\n" \
3009 " 7663/7921 group\n" \
3010 " Group0: CH0 - 3 Group1: CH4 - 8 Group2: CH9 - 13 Group3: CH14 - 18\n" \
3011 " Group4: CH19 - 23 Group5: CH24 - 28 Group6: CH29 - 33 Group7: CH34 - 38\n" \
3012 " Group8: CH39 - 43 Group9: CH44 - 48 Group10:CH49 - 53 Group11:CH54 - 58\n" \
3013 " Group12:CH59 - 63 Group13:CH64 - 68 Group14:CH69 - 73 Group15:CH74 - 78\n" \
3014 " The following ONLY for 7668\n" \
3015 " [r] RF CR for level 8 GroupX:\n" \
3016 " [i] Level 8 GroupX:\n" \
3017 " [e] ePA GroupX:\n" \
3018 " Group0: CH0 - 12 Group1: CH13 - 25 Group2: CH26 - 38\n" \
3019 " Group3: CH39 - 51 Group4: CH52 - 64 Group5: CH65 - 78\n" \
3020 " <-16~8>: Unit is +/-0.25db per step and 0 is default value\n" \
3021 " Note: set -i only, Boots will use stage 1, set -r and -i together, Boots will use stage 2.\n" \
3022 " EX: [7662/7668] # ./boots -c txpwoffset -g0 6 -g1 5 -g2 4 -g3 3 -g4 2 -g5 1\n" \
3023 " [7668 only] # ./boots -c txpwoffset -g0 6 ... -r0 4 ... -i0 6 ... -e0 8 ...\n" \
3024 " [7663/7921] # ./boots -c txpwoffset -g0 6 ... -g15 8\n" \
3025 " [7663/7921] # ./boots -c txpwoffset g16 -g0 6"
3026#define USAGE_WH_DETAILS \
3027 " EX: # ./boots -c whiten 1"
3028#define USAGE_SYNC_DETAILS \
3029 " EX: # ./boots -c sync 11:33:55:77:99:BB:DD:FF"
3030#define USAGE_EFUSE_WR_PREFACE \
3031 "Read/Write eFuse [-r/w] [-a <HEX:0-0xFFFF>] [-v <HEX:0-0xFF>]"
3032#define USAGE_EFUSE_WR_DETAILS \
3033 " [w] Write: write efuse value\n" \
3034 " [r] Read: read efuse value\n" \
3035 " [a] Addr: address of efuse\n" \
3036 " [v] Value: value of efuse\n" \
3037 " EX: # ./boots -c efuse -r -a 1A5F"
3038#define USAGE_REGISTER_WR_PREFACE \
3039 "Read/Write Register [-r/w] [-a <HEX:0-0xFFFFFFFF>] [-v <HEX:0-0xFFFFFFFF>]"
3040#define USAGE_REGISTER_WR_DETAILS \
3041 " [w] Write: write register value\n" \
3042 " [r] Read: read register value\n" \
3043 " [a] Addr: address of register\n" \
3044 " [v] Value: value of register\n" \
3045 " EX: # ./boots -c reg -r -a 11111111"
3046#define USAGE_FILE_WR_PREFACE \
3047 "Read/Write File [-r/w] [-a <HEX>] [-v <HEX:0-0xFF>] [-f <file_path>]"
3048#define USAGE_FILE_WR_DETAILS \
3049 " [w] Write: write bin_file value\n" \
3050 " [r] Read: read bin_file value\n" \
3051 " [a] Addr: offset of bin_file\n" \
3052 " [v] Value: value of bin_file\n" \
3053 " [f] File path: full path and name of bin file\n" \
3054 " EX: # ./boots -c file -w -a 0 -v 6 -f boots.bin"
3055#define USAGE_STT_PREFACE \
3056 "Stress test using \"Write Local Name HCI Command\" <pkt size 1-248>"
3057#define USAGE_STT_DETAILS \
3058 " EX: # ./boots -c stt 248"
3059#define USAGE_LBT_PREFACE \
3060 "Loopback test using \"ACL packet\" <pkt size 1-1021>"
3061#define USAGE_LBT_DETAILS \
3062 " EX: # ./boots -c lbt 255"
3063#define USAGE_LTT_PREFACE \
3064 "Loopback test with timer using \"ACL packet\" [-t <ms>] [-s <pkt size>]"
3065#define USAGE_LTT_DETAILS \
3066 " EX: # ./boots -c ltt -t 100 -s 255"
3067#define USAGE_PA_DETAILS \
3068 " EX: # ./boots -c pa 1"
3069#define USAGE_DUPLEX_DETAILS \
3070 " EX: # ./boots -c duplex 1"
3071#define USAGE_BG_RSSI_PREFACE \
3072 "Enable/Disable background RSSI scan <0/1> [-o <0/1>] [-s <0-78>] [-e <0-78>] [-a <DEC>] [-f <DEC>] [-n <0/1>]"
3073#define USAGE_BG_RSSI_DETAILS \
3074 " <0/1> 0:disable 1:enable\n" \
3075 " 1: mt7668 will continue report rssi value for each channels and packages\n" \
3076 " Boots will output it to the log depend on the setting parameter.\n" \
3077 " [o] Output: output report when disable background rssi, 0:disable 1:enable\n" \
3078 " [s] Start channel: 0-78. default:0\n" \
3079 " [e] End channel: 0-78. default:78\n" \
3080 " [a] Average package(s): calculate average when gatting n rssi channel packages. default:1\n" \
3081 " [f] Alpha filter: calculate 1/n alpha filter for each rssi channel packages.\n" \
3082 " [n] Report once: display only one report and stop background rssi immediately. 0:disable 1:enable\n" \
3083 " EX: # ./boots -c rssi 1 -o 1 -s 0 -e 78 -f 100"
3084#define USAGE_PK_RSSI_DETAILS \
3085 " [a] Handle: handle to get rssi value, if ignore this boots will use the default value: 0x0032\n" \
3086 " EX: # ./boots -c pk_rssi"
3087#define USAGE_BUF_MODE_DETAILS \
3088 " EX: # ./boots -c buf_mode -e 1"
3089#define CMD_BUF_MODE "buf_mode"
3090#define USAGE_TX_HOPPING_PREFACE \
3091 "Set hopping 20 channel: low/middle/high\n" \
3092 " low: hopping 2402~2421MHz\n" \
3093 " middle: hopping 2432~2451MHz\n" \
3094 " high: hopping 2461~2480MHz"
3095#define USAGE_TX_HOPPING_DETAILS \
3096 " EX: # ./boots -c tx_hopping low"
3097#define USAGE_SWITCH_BT_PREFACE \
3098 "Switch BT0/1 <0:BT0/1:BT1>" \
3099 RED"(for 7921)"NONE
3100#define USAGE_SWITCH_BT_DETAILS \
3101 " EX: # ./boots -c swbt 0"
3102#define USAGE_POWER_COMPENSATION_PREFACE \
3103 "Power compensation [-a <0/1>] [-l <0-3>]" \
3104 RED"(for 7921)\n"NONE \
3105 " 7921(6 groups):\n" \
3106 " [-g0 <-16~16>] [-g1 <-16~16>] [-g2 <-16~16>] [-g3 <-16~16>] [-g4 <-16~16>] [-g5 <-16~16>]"
3107#define USAGE_POWER_COMPENSATION_DETAILS \
3108 " [a] Antenna index: 0: Antenna0 1: Antenna1\n" \
3109 " [l] Offset level: 0: LMAX offset 1: LMAX-1 offset\n" \
3110 " 2: LMAX-2 offset 3: LMAX-3 offset\n" \
3111 " [g] GroupX: 7921 have 6 groups\n" \
3112 " EX: # ./boots -c pwcomp -a 0 -l 1 -g0 6 -g1 5 -g2 4 -g3 3 -g4 2 -g5 1"
3113#define USAGE_POWER_BOUNDARY_PREFACE \
3114 "Power boundary [-a <0/1>]" \
3115 RED"(for 7921)\n"NONE \
3116 " 7921(5 boundaries):\n" \
3117 " [-b0 <0~80>] [-b1 <0~79>] [-b2 <0~79>] [-b3 <0~79>] [-b4 <0~79>]"
3118#define USAGE_POWER_BOUNDARY_DETAILS \
3119 " [a] Antenna index: 0: Antenna0, 1: Antenna1\n" \
3120 " [b] BoundaryX: 7921 can set 5 boundaries\n" \
3121 " EX: # ./boots -c pwbdry -a 0 -b0 12 -b1 21 -b2 45 -b3 60 -b4 79"
3122#define USAGE_SET_SX_TX_PREFACE \
3123 "Set SX TX Type" \
3124 RED"(for 7921)\n"NONE \
3125 " BT0/1 according to SWITCH_BT command setting\n" \
3126 " BT0 SX Configration: 1: DIV2 for Rx , 3: SSB 8/3 for T/Rx\n" \
3127 " 4: SSB 16/5 for T/Rx, 5: DIV2 LP for Rx\n" \
3128 " BT1 SX Configration: 0: VCDL 5/2 for T/Rx, 1: DIV2 for Rx\n" \
3129 " 2: VCDL 7/2 for T/Rx, 5: DIV2 LP for Rx"
3130#define USAGE_SET_SX_TX_DETAILS \
3131 " EX: # ./boots -c sxtx 0"
3132#define USAGE_SET_SX_RX_PREFACE \
3133 "Set SX RX Type" \
3134 RED"(for 7921)\n"NONE \
3135 " BT0/1 according to SWITCH_BT command setting\n" \
3136 " BT0 SX Configration: 1: DIV2 for Rx , 3: SSB 8/3 for T/Rx\n" \
3137 " 4: SSB 16/5 for T/Rx, 5: DIV2 LP for Rx\n" \
3138 " BT1 SX Configration: 0: VCDL 5/2 for T/Rx, 1: DIV2 for Rx\n" \
3139 " 2: VCDL 7/2 for T/Rx, 5: DIV2 LP for Rx"
3140#define USAGE_SET_SX_RX_DETAILS \
3141 " EX: # ./boots -c sxrx 0"
3142#define USAGE_ANT_TO_PIN_LOSS_PREFACE \
3143 "Set ANT-to-ChipPin loss 1dB/step, suggested range from 0-5dB" \
3144 RED"(for 7921)\n"NONE \
3145 " <0~20> 0.25dB/step"
3146#define USAGE_ANT_TO_PIN_LOSS_DETAILS \
3147 " EX: # ./boots -c a2ploss 0"
3148#define USAGE_READ_EDR_INFO_PREFACE \
3149 "Read EDR infomation" \
3150 RED"(for 7921)"NONE
3151#define USAGE_READ_EDR_INFO_DETAILS \
3152 " EX: # ./boots -c redrinfo"
3153#define USAGE_EPA_ELNA_PREFACE \
3154 "ePA/eLNA 0: disable 1: enable" \
3155 RED"(for 7921)"NONE
3156#define USAGE_EPA_ELNA_DETAILS \
3157 " [p] ePA: 0: disable, 1: enable\n" \
3158 " [l] eLNA: 0: disable, 1: enable\n" \
3159 " EX: # ./boots -c palna -p 0 -l 0"
3160#define USAGE_SWITCH_RX_MODE_PREFACE \
3161 "Switch RX normal mode/low power mode" \
3162 RED"(for 7921)\n"NONE \
3163 " 1: div2 normal mode, 5: div2 low power mode"
3164#define USAGE_SWITCH_RX_MODE_DETAILS \
3165 " EX: # ./boots -c swrxmode 1"
3166#define USAGE_SET_XO_MODE_PREFACE \
3167 "Set XO mode 0: AX mode 1: BT Mode" \
3168 RED"(for 7921)"NONE
3169#define USAGE_SET_XO_MODE_DETAILS \
3170 " EX: # ./boots -c setxo 1"
3171#define USAGE_GET_XO_MODE_PREFACE \
3172 "Get XO mode 0: AX mode 1: BT Mode" \
3173 RED"(for 7921)"NONE
3174#define USAGE_GET_XO_MODE_DETAILS \
3175 " EX: # ./boots -c getxo"
3176#define USAGE_BT_MODE_XO_TRIM_PREFACE \
3177 "BT mode XO trim [-f <5~127>] [-x <-63~63>] [-y <-63~63>] [-z <-63~63>]" \
3178 RED"(for 7921)"NONE
3179#define USAGE_BT_MODE_XO_TRIM_DETAILS \
3180 " [f] Frequency offset ( XO_C1_SEL_BTM)\n" \
3181 " [x] XO trim2 compensation (XO_C1_SEL_BTM)\n" \
3182 " [y] XO trim3 compensation (XO_C1_SEL_BTM)\n" \
3183 " [z] XO trim4 compensation (XO_C1_SEL_BTM)\n" \
3184 " EX: # ./boots -c trimxo -f 10 -x 10 -y 10 -z 10"
3185
3186boots_cmds_s commands[] = {
3187 { "reset", mtk_boots_cmd_reset, "HCI Reset", USAGE_RESET_DETAILS, false },
3188 { "inq", mtk_boots_cmd_inquiry, "Inquiry [-t <X * 1.28 sec>]", USAGE_INQ_DETAILS, false },
3189 { "dut", mtk_boots_cmd_enter_dut, "Enter DUT mode", USAGE_DUT_DETAILS, false },
3190 { "raddr", mtk_boots_cmd_read_bd_addr, "Read BD address", USAGE_RADDR_DETAILS, false },
3191 { "waddr", mtk_boots_cmd_write_bd_addr, "Write BD address <0E:8D:76:68:00:01>", USAGE_WADDR_DETAILS, false },
3192 { "pwrlvl", mtk_boots_cmd_set_power_level, "Set power level(0xFC17) ONLY for RFTX since per link handle <0-7>", USAGE_PWRL_DETAILS, false },
3193 { "radio", mtk_boots_cmd_radio_setting, USAGE_RADIOSETTING_PREFACE, USAGE_RADIOSETTING_DETAILS, false },
3194 { "txpow", mtk_boots_cmd_tx_power_setting, USAGE_TXPOWSETTING_PREFACE, USAGE_TXPOWSETTING_DETAILS, false },
3195 { "txpwoffset", mtk_boots_cmd_tx_power_offset, USAGE_TXPOWEROFFSET_PREFACE, USAGE_TXPOWEROFFSET_DETAILS, false },
3196 { "whiten", mtk_boots_cmd_set_whiten, "Set whiten <0:disable/1:enable>", USAGE_WH_DETAILS, false },
3197 { "sync", mtk_boots_cmd_sync, "Access Code <XX:XX:XX:XX:XX:XX:XX:XX>", USAGE_SYNC_DETAILS, false },
3198 { "rft", mtk_boots_cmd_rf_tx, USAGE_RFTX_PREFACE, USAGE_RFTX_DETAILS, false },
3199 { "rfr", mtk_boots_cmd_rf_rx, USAGE_RFRX_PREFACE, USAGE_RFRX_DETAILS RFR_EX, false },
3200 { "rf_stop", mtk_boots_cmd_rf_stop, USAGE_RF_STOP_PREFACE, USAGE_RF_STOP_DETAILS, false },
3201 { "rfr_stop", mtk_boots_cmd_rf_rx, USAGE_RFRX_STOP_PREFACE, USAGE_RFRX_DETAILS RFR_S_EX, false },
3202 { "rfr_result", mtk_boots_cmd_rf_rx, USAGE_RFRX_RESULT_PREFACE, USAGE_RFRX_DETAILS RFR_R_EX, false },
3203 { "ble_tx", mtk_boots_cmd_ble_tx, USAGE_BLETX_PREFACE, USAGE_BLETX_DETAILS, false },
3204 { "ble_rx", mtk_boots_cmd_ble_rx, "BLE RX test [-c <0-39>]", USAGE_BLERX_DETAILS, false },
3205 { "ble_etx", mtk_boots_cmd_ble_etx, USAGE_BLEETX_PREFACE, USAGE_BLEETX_DETAILS, false },
3206 { "ble_erx", mtk_boots_cmd_ble_erx, USAGE_BLEERX_PREFACE, USAGE_BLEERX_DETAILS, false },
3207 { "ble_stop", mtk_boots_cmd_ble_test_stop, "Stop BLE test", USAGE_BLE_S_DETAILS, false },
3208 { "txtone", mtk_boots_cmd_tx_tone, USAGE_TXTONE_PREFACE, USAGE_TXTONE_DETAILS, false },
3209 { "efuse", mtk_boots_cmd_efuse_wr, USAGE_EFUSE_WR_PREFACE, USAGE_EFUSE_WR_DETAILS, false },
3210 { "reg", mtk_boots_cmd_register_wr, USAGE_REGISTER_WR_PREFACE, USAGE_REGISTER_WR_DETAILS, true },
3211 { "file", mtk_boots_cmd_file_wr, USAGE_FILE_WR_PREFACE, USAGE_FILE_WR_DETAILS, true },
3212 { "stt", mtk_boots_cmd_stress_test, USAGE_STT_PREFACE, USAGE_STT_DETAILS, false },
3213 { "lbt", mtk_boots_cmd_loop_back_test, USAGE_LBT_PREFACE, USAGE_LBT_DETAILS, false },
3214 { "ltt", mtk_boots_cmd_loop_timer_test, USAGE_LTT_PREFACE, USAGE_LTT_DETAILS, false },
3215 { "pa", mtk_boots_cmd_set_pa, "Set ePA or iPA <0:iPA/1:ePA> ONLY for 7668", USAGE_PA_DETAILS, false },
3216 { "duplex", mtk_boots_cmd_set_ant, "Set TDD mode(ANT1) or FDD mode(ANT2) <0:FDD/1:TDD>", USAGE_DUPLEX_DETAILS, false },
3217 { "rssi", mtk_boots_cmd_background_rssi_scan, USAGE_BG_RSSI_PREFACE, USAGE_BG_RSSI_DETAILS, false },
3218 { "pk_rssi", mtk_boots_cmd_packet_rssi, "Get BT packet RSSI [-a <HEX>]", USAGE_PK_RSSI_DETAILS, false },
3219 { CMD_BUF_MODE, mtk_boots_cmd_set_buffer_mode, "Set buffer mode [-f <file_path>] [-e <0:disable/1:enable>]", USAGE_BUF_MODE_DETAILS, false },
3220 { "tx_hopping", mtk_boots_cmd_set_tx_hopping, USAGE_TX_HOPPING_PREFACE, USAGE_TX_HOPPING_DETAILS, false },
3221 { "swbt", mtk_boots_cmd_switch_bt, USAGE_SWITCH_BT_PREFACE, USAGE_SWITCH_BT_DETAILS, false },
3222 { "pwcomp", mtk_boots_cmd_power_compensation, USAGE_POWER_COMPENSATION_PREFACE, USAGE_POWER_COMPENSATION_DETAILS, false },
3223 { "pwbdry", mtk_boots_cmd_power_boundary, USAGE_POWER_BOUNDARY_PREFACE, USAGE_POWER_BOUNDARY_DETAILS, false },
3224 { "sxtx", mtk_boots_cmd_set_sx, USAGE_SET_SX_TX_PREFACE, USAGE_SET_SX_TX_DETAILS, true },
3225 { "sxrx", mtk_boots_cmd_set_sx, USAGE_SET_SX_RX_PREFACE, USAGE_SET_SX_RX_DETAILS, true },
3226 { "a2ploss", mtk_boots_cmd_ant_to_pin_loss, USAGE_ANT_TO_PIN_LOSS_PREFACE, USAGE_ANT_TO_PIN_LOSS_DETAILS, false },
3227 { "redrinfo", mtk_boots_cmd_read_edr_info, USAGE_READ_EDR_INFO_PREFACE, USAGE_READ_EDR_INFO_DETAILS, false },
3228 { "palna", mtk_boots_cmd_epa_elna, USAGE_EPA_ELNA_PREFACE, USAGE_EPA_ELNA_DETAILS, false },
3229 { "swrxmode", mtk_boots_cmd_set_sx, USAGE_SWITCH_RX_MODE_PREFACE, USAGE_SWITCH_RX_MODE_DETAILS, true },
3230 { "setxo", mtk_boots_cmd_set_xomode, USAGE_SET_XO_MODE_PREFACE, USAGE_SET_XO_MODE_DETAILS, false },
3231 { "getxo", mtk_boots_cmd_get_xomode, USAGE_GET_XO_MODE_PREFACE, USAGE_GET_XO_MODE_DETAILS, false },
3232 { "trimxo", mtk_boots_cmd_bt_xo_trim, USAGE_BT_MODE_XO_TRIM_PREFACE, USAGE_BT_MODE_XO_TRIM_DETAILS, false },
3233 { NULL, NULL, NULL, NULL, NULL }
3234};
3235
3236//---------------------------------------------------------------------------
3237pkt_list_s *boots_raw_cmd_handler(char *raw[], size_t len)
3238{
3239 size_t i = 0;
3240 uint8_t type = 0;
3241 pkt_list_s *node = NULL;
3242
3243 if (!raw || len < 4) {
3244 BPRINT_E("Incorrect input(len: %d)", (int)len);
3245 return 0;
3246 }
3247
3248 if (!memcmp(raw[0], "CMD", strlen(raw[0])) || !memcmp(raw[0], "cmd", strlen(raw[0]))) {
3249 size_t rawlen = strtol(raw[3], NULL, 16);
3250 if (len != rawlen + 4) {
3251 BPRINT_E("Incorrect command length: %d", (int)rawlen);
3252 return 0;
3253 }
3254 type = 0x01;
3255 i = 1;
3256 } else if (!memcmp(raw[0], "ACL", strlen(raw[0])) || !memcmp(raw[0], "acl", strlen(raw[0]))) {
3257 type = 0x02;
3258 i = 1;
3259 } else if (!memcmp(raw[0], "SCO", strlen(raw[0])) || !memcmp(raw[0], "sco", strlen(raw[0]))) {
3260 BPRINT_E("%s: SCO not support yet", __func__);
3261 return 0;
3262 } else {
3263 BPRINT_E("%s: Incorrect argument", __func__);
3264 return 0;
3265 }
3266
3267 node = boots_pkt_node_push(SCRIPT_NONE, type, NULL, len, NULL, NULL);
3268 if (!node) {
3269 BPRINT_D("%s: node push fail", __func__);
3270 return NULL;
3271 }
3272
3273 node->u_cnt.data[0] = type;
3274 while (raw[i] && i < len) {
3275 node->u_cnt.data[i] = strtol(raw[i], NULL, 16);
3276 i++;
3277 }
3278 node->len = i;
3279 // TODO check packet length & content
3280 return node; // actually raw data length
3281}
3282
3283//---------------------------------------------------------------------------
3284pkt_list_s *boots_cmd_set_handler(char *cmd[], size_t len)
3285{
3286 uint8_t i = 0;
3287 pkt_list_s *list = NULL;
3288
3289 if (!cmd || !len) return NULL;
3290
3291 for (i = 0; i < ARRAY_SIZE(commands); i++) {
3292 if (commands[i].cmd && !memcmp(cmd[0], commands[i].cmd, strlen(cmd[0]))) {
3293 if ((list = commands[i].func(cmd, len)) == NULL) {
3294 // ignore this command since no controller operation
3295 if (memcmp(*cmd, CMD_BUF_MODE, strlen(CMD_BUF_MODE)))
3296 BPRINT_I("%s\n%s", commands[i].comment, commands[i].details);
3297 return NULL;
3298 } else {
3299 return list;
3300 }
3301 }
3302 }
3303 BPRINT_I("%s: Command Not Found(%s)", __func__, cmd[0]);
3304
3305 return NULL;
3306}
3307
3308//---------------------------------------------------------------------------