4853 lines
132 KiB
C
4853 lines
132 KiB
C
/*
|
|
* Copyright (c) 2008-2009 Atheros Corporation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation;
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* <Configuration utility for AR3001>
|
|
*
|
|
* <btconfig.c>
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <sys/param.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
#include <bluetooth/bluetooth.h>
|
|
#include <bluetooth/hci.h>
|
|
#include <bluetooth/hci_lib.h>
|
|
|
|
#include "btconfig.h"
|
|
#include "masterblaster.h"
|
|
|
|
/* Global Variables */
|
|
static int Tag_Count = 0;
|
|
static int Patch_Count = 0;
|
|
static unsigned short DynMem_Count = 0;
|
|
static int Total_tag_lenght = 0;
|
|
static BOOL CtrlCBreak = FALSE;
|
|
bdaddr_t BdAddr;
|
|
/* Function Declarations */
|
|
static int LoadConfFile(const char *path, int basetag, int format);
|
|
static int ParseFiles(FILE *fpt, int basetag, int format);
|
|
static void LoadPSHeader(UCHAR *HCI_PS_Command,UCHAR opcode,int length,int index);
|
|
static BOOL PSOperations(int dd, UCHAR Opcode, int Param1, UINT32 *out);
|
|
static BOOL SU_LERxTest(int dev_id, UCHAR channel);
|
|
static BOOL SU_LETxTest(int dev_id, UCHAR channel, UCHAR length, UCHAR payload);
|
|
static int PSInit(int dd);
|
|
static void usage(void);
|
|
static int writeHciCommand(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, UCHAR *buf);
|
|
static int MemBlkRead(int dd, UINT32 Address,UCHAR *pBuffer, UINT32 Length);
|
|
static int MemBlkwrite(int dd, UINT32 Address,UCHAR *pBuffer, UINT32 Length);
|
|
static int Dut(int dd);
|
|
static int ReadAudioStats(int dd);
|
|
static int ReadGlobalDMAStats(int dd);
|
|
static int ResetGlobalDMAStats(int dd);
|
|
static int ReadTpcTable(int dd);
|
|
static int ReadHostInterest(int dd,tBtHostInterest *pHostInt);
|
|
static int ReadMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length );
|
|
static int WriteMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length );
|
|
static int write_otpRaw(int dev_id, int address, int length, UCHAR *data);
|
|
static int read_otpRaw(int dev_id, int address, int length, UCHAR *data);
|
|
static void dumpHex(UCHAR *buf, int length, int col);
|
|
static void sig_term(int sig);
|
|
static UCHAR LEMode = 0;
|
|
|
|
static struct option main_options[] = {
|
|
{ "help", 0, 0, 'h' },
|
|
{ "device", 1, 0, 'i' },
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
//Read the configuration files, file paths are hardcoded in btconfig.h
|
|
static int LoadConfFile(const char *path, int basetag, int format){
|
|
|
|
FILE *fp;
|
|
//printf("\nOpening file :%s\n",path);
|
|
fp = fopen(path,"r");
|
|
if(fp == NULL){
|
|
// perror("File open error");
|
|
return FALSE;
|
|
}
|
|
// Parse file
|
|
if(!ParseFiles(fp,basetag,format)){
|
|
printf("\nError :Invalid file format\n");
|
|
return FALSE;
|
|
}
|
|
// Load conf data to PS
|
|
|
|
fclose(fp);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
unsigned int uGetInputDataFormat(char **str, struct ST_PS_DATA_FORMAT *pstFormat)
|
|
{
|
|
char *pCharLine = *str;
|
|
if(pCharLine[0] != '[') {
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
return TRUE;
|
|
}
|
|
switch(pCharLine[1]) {
|
|
case 'H':
|
|
case 'h':
|
|
if(pCharLine[2]==':') {
|
|
if((pCharLine[3]== 'a') || (pCharLine[3]== 'A')) {
|
|
if(pCharLine[4] == ']') {
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 5;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else {
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); //[H:A
|
|
return FALSE;
|
|
}
|
|
}
|
|
if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) {
|
|
if(pCharLine[4] == ']') {
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = FALSE;
|
|
//pCharLine += 5;
|
|
*str += 5;
|
|
//printf("\nDEBUG H-1:%s\n",pCharLine);
|
|
return TRUE;
|
|
}
|
|
else {
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); //[H:A
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if(pCharLine[3] == ']') { //[H:]
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 4;
|
|
*str += 4;
|
|
return TRUE;
|
|
}
|
|
else { //[H:
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if(pCharLine[2]==']') { //[H]
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 3;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else { //[H
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case 'A':
|
|
case 'a':
|
|
if(pCharLine[2]==':') {
|
|
if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
|
|
if(pCharLine[4] == ']') {
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 5;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else {
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); //[A:H
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if(pCharLine[3]== ']') { //[A:]
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 4;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else { //[A:
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if(pCharLine[2]==']') { //[H]
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 3;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else { //[H
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case 'S':
|
|
case 's':
|
|
if(pCharLine[2]==':') {
|
|
if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
|
|
if(pCharLine[4] == ']') {
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 5;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else {
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");//[A:H
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if(pCharLine[3]== ']') { //[A:]
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 4;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else { //[A:
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if(pCharLine[2]==']') { //[H]
|
|
pstFormat->eDataType = eHex;
|
|
pstFormat->bIsArray = TRUE;
|
|
//pCharLine += 3;
|
|
*str += 5;
|
|
return TRUE;
|
|
}
|
|
else { //[H
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
printf("\nuGetInputDataFormat - Invalid Data Format \r\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
unsigned int uReadDataInSection(char *pCharLine, struct ST_PS_DATA_FORMAT stPS_DataFormat)
|
|
{
|
|
if(stPS_DataFormat.eDataType == eHex) {
|
|
if(stPS_DataFormat.bIsArray == TRUE) {
|
|
//Not implemented
|
|
printf("\nNO IMP\n");
|
|
return (0x0FFF);
|
|
}
|
|
else {
|
|
//printf("\nDEBUG H-2 %d\n",strtol(pCharLine, NULL, 16));
|
|
return (strtol(pCharLine, NULL, 16));
|
|
}
|
|
}
|
|
else {
|
|
//Not implemented
|
|
printf("\nNO IMP-1\n");
|
|
return (0x0FFF);
|
|
}
|
|
}
|
|
|
|
|
|
static int ParseFiles(FILE *fpt, int basetag, int format){
|
|
int i,j,k,linecnt,ByteCount=0,ByteCount_Org =0,data,Cnt;
|
|
char *str,line[LINE_SIZE_MAX],byte[3];
|
|
int ParseSelection=RAM_PS_SECTION;
|
|
struct ST_PS_DATA_FORMAT stPS_DataFormat;
|
|
struct ST_READ_STATUS stReadStatus = {0, 0, 0,0};
|
|
unsigned int uReadCount;
|
|
|
|
switch(format){
|
|
case MB_FILEFORMAT_PS:
|
|
linecnt = 0;
|
|
j=0;
|
|
|
|
while ((str = fgets(line, LINE_SIZE_MAX, fpt)) != NULL) {
|
|
SKIP_BLANKS(str);
|
|
//Comment line
|
|
if ((str[0]== '/') && (str[1]== '/'))
|
|
continue;
|
|
|
|
if (str[0]== '#'){
|
|
if (stReadStatus.uSection != 0){
|
|
printf("\nParseFiles - Invalid file format %d\r\n",ParseSelection);
|
|
return FALSE;
|
|
}
|
|
else {
|
|
stReadStatus.uSection = 1;
|
|
continue;
|
|
}
|
|
|
|
}
|
|
if ((str[0]== '/') && (str[1]== '*'))
|
|
{
|
|
str+=2;
|
|
SKIP_BLANKS(str);
|
|
if(!strncmp(str,"PA",2)||!strncmp(str,"Pa",2)||!strncmp(str,"pa",2)){
|
|
|
|
ParseSelection=RAM_PATCH_SECTION;
|
|
}
|
|
if(!strncmp(str,"DY",2)||!strncmp(str,"Dy",2)||!strncmp(str,"dy",2)){
|
|
|
|
ParseSelection=RAM_DYN_MEM_SECTION;
|
|
}
|
|
if(!strncmp(str,"PS",2)||!strncmp(str,"Ps",2)||!strncmp(str,"ps",2)){
|
|
|
|
ParseSelection=RAM_PS_SECTION;
|
|
}
|
|
linecnt = 0;
|
|
stReadStatus.uSection = 0;
|
|
continue;
|
|
}
|
|
|
|
switch(ParseSelection){
|
|
|
|
case RAM_PS_SECTION:
|
|
if (stReadStatus.uSection == 1){ //TagID
|
|
SKIP_BLANKS(str);
|
|
if(!uGetInputDataFormat(&str, &stPS_DataFormat)) {
|
|
return FALSE;
|
|
}
|
|
PsTagEntry[Tag_Count].TagId = uReadDataInSection(str, stPS_DataFormat);
|
|
stReadStatus.uSection = 2;
|
|
}
|
|
else if (stReadStatus.uSection == 2){ //TagLength
|
|
if(!uGetInputDataFormat(&str, &stPS_DataFormat)) {
|
|
return FALSE;
|
|
}
|
|
ByteCount = uReadDataInSection(str, stPS_DataFormat);
|
|
|
|
if (ByteCount > RAMPS_MAX_PS_DATA_PER_TAG){
|
|
printf("\nParseFiles - INVALID %d: One of the table exceeds maximum table size of %d\r\n",ParseSelection, MAX_RADIO_CFG_TABLE_SIZE);
|
|
return FALSE;
|
|
}
|
|
PsTagEntry[Tag_Count].TagLen = (ByteCount & 0xFF);
|
|
stReadStatus.uSection = 3;
|
|
stReadStatus.uLineCount = 0;
|
|
}
|
|
else if( stReadStatus.uSection == 3) { //Data
|
|
if(stReadStatus.uLineCount == 0) {
|
|
if(!uGetInputDataFormat(&str,&stPS_DataFormat)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
SKIP_BLANKS(str);
|
|
stReadStatus.uCharCount = 0;
|
|
uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount;
|
|
if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == TRUE) {
|
|
while(uReadCount > 0) {
|
|
PsTagEntry[Tag_Count].TagData[stReadStatus.uByteCount] = (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount]) << 4) | (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount + 1]));
|
|
PsTagEntry[Tag_Count].TagData[stReadStatus.uByteCount+1] = (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount + 3]) << 4) | (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount + 4]));
|
|
stReadStatus.uCharCount += 6; // read two bytes, plus a space;
|
|
stReadStatus.uByteCount += 2;
|
|
uReadCount -= 2;
|
|
}
|
|
|
|
if(ByteCount > BYTES_OF_PS_DATA_PER_LINE) {
|
|
ByteCount -= BYTES_OF_PS_DATA_PER_LINE;
|
|
}
|
|
else {
|
|
ByteCount = 0;
|
|
}
|
|
}
|
|
else {
|
|
//to be implemented
|
|
printf("\nParseFiles - To be implemented");
|
|
}
|
|
|
|
stReadStatus.uLineCount++;
|
|
|
|
if(ByteCount == 0) {
|
|
stReadStatus.uSection = 0;
|
|
stReadStatus.uCharCount = 0;
|
|
stReadStatus.uLineCount = 0;
|
|
stReadStatus.uByteCount = 0;
|
|
}
|
|
else {
|
|
stReadStatus.uCharCount = 0;
|
|
}
|
|
|
|
if((stReadStatus.uSection == 0)&&(++Tag_Count == RAMPS_MAX_PS_TAGS_PER_FILE))
|
|
{
|
|
printf("\n ParseFiles - INVALID %d: Number of tables exceeds %d\r\n",ParseSelection, RAMPS_MAX_PS_TAGS_PER_FILE);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
printf("\nParseFiles - Invalid file format %d\r\n",ParseSelection);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
|
|
}
|
|
linecnt++;
|
|
}
|
|
break;
|
|
case MB_FILEFORMAT_DY:
|
|
{
|
|
linecnt = 0;
|
|
while ((str = fgets(line, LINE_SIZE_MAX, fpt)) != NULL) {
|
|
SKIP_BLANKS(str);
|
|
//Comment line
|
|
if ((str[0]== '/') && (str[1]== '/'))
|
|
continue;
|
|
|
|
if ((str[0]== '/') && (str[1]== '*'))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
if((linecnt % 2) == 0)
|
|
{
|
|
ByteCount = (UINT16)strtol(str, NULL, 16);
|
|
RamDynMemOverride.Len= (ByteCount & 0xFF);
|
|
}
|
|
else
|
|
{
|
|
for (i=0,k=0; k < ByteCount; i += 2,k++) {
|
|
memcpy(byte, &str[i], 2);
|
|
byte[2] = '\0';
|
|
data = strtoul(byte, NULL, 16);
|
|
RamDynMemOverride.Data[k] = (data & 0xFF);
|
|
}
|
|
DynMem_Count = TRUE;
|
|
}
|
|
linecnt++;
|
|
}
|
|
}
|
|
break;
|
|
case MB_FILEFORMAT_PATCH:
|
|
{
|
|
j=0;
|
|
Cnt=0;
|
|
linecnt = 0;
|
|
while ((str = fgets(line, LINE_SIZE_MAX, fpt)) != NULL) {
|
|
SKIP_BLANKS(str);
|
|
//Comment line
|
|
if ((str[0]== '/') && (str[1]== '/'))
|
|
continue;
|
|
|
|
if ((str[0]== '/') && (str[1]== '*'))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(linecnt==0)
|
|
{
|
|
ByteCount = (UINT16)strtol(str, NULL, 16);
|
|
ByteCount_Org = ByteCount;
|
|
while(ByteCount > MAX_BYTE_LENGTH){
|
|
RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH;
|
|
Patch_Count ++;
|
|
ByteCount= ByteCount - MAX_BYTE_LENGTH;
|
|
}
|
|
RamPatch[Patch_Count].Len= (ByteCount & 0xFF);
|
|
Patch_Count ++;
|
|
|
|
}
|
|
else
|
|
{
|
|
while(ByteCount_Org > MAX_BYTE_LENGTH){
|
|
for (i = 0, k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++) {
|
|
memcpy(byte, &str[Cnt], 2);
|
|
byte[2] = '\0';
|
|
data = strtoul(byte, NULL, 16);
|
|
RamPatch[j].Data[k] = (data & 0xFF);
|
|
Cnt += 2;
|
|
}
|
|
j++;
|
|
ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH;
|
|
}
|
|
if(j == 0){
|
|
j++;
|
|
}
|
|
for (k=0; k < ByteCount_Org;k++) {
|
|
memcpy(byte, &str[Cnt], 2);
|
|
byte[2] = '\0';
|
|
data = strtoul(byte, NULL, 16);
|
|
RamPatch[j].Data[k] = (data & 0xFF);
|
|
Cnt += 2;
|
|
}
|
|
}
|
|
|
|
linecnt++;
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static void LoadPSHeader(UCHAR *HCI_PS_Command,UCHAR opcode,int length,int index) {
|
|
|
|
HCI_PS_Command[0]= opcode;
|
|
HCI_PS_Command[1]= (index & 0xFF);
|
|
HCI_PS_Command[2]= ((index>>8) & 0xFF);
|
|
HCI_PS_Command[3]= length;
|
|
|
|
}
|
|
|
|
|
|
static BOOL PSOperations(int dd, UCHAR Opcode, int Param1, UINT32 *out) {
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int Length,i,j,iRet;
|
|
memset(&buf,0,sizeof(buf));
|
|
switch(Opcode){
|
|
case WRITE_PATCH:
|
|
for(i=0;i< Param1;i++){
|
|
LoadPSHeader(buf,Opcode,RamPatch[i].Len,i);
|
|
for(j=0;j<RamPatch[i].Len;j++){
|
|
buf[4+j]=RamPatch[i].Data[j];
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_PS,RamPatch[i].Len + PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0){
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ENABLE_PATCH:
|
|
Length =0;
|
|
i=0;
|
|
LoadPSHeader(buf,Opcode,Length,i);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0){
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case PS_RESET:
|
|
Length =0;
|
|
i=0;
|
|
LoadPSHeader(buf,Opcode,Length,i);
|
|
buf[8] = (Param1 & 0xFF);
|
|
buf[9] = ((Param1 >> 8) & 0xFF);
|
|
Length = 6;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,Length + PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0){
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case PS_READ: {
|
|
UCHAR *len = (UCHAR *)out;
|
|
ssize_t plen = 0;
|
|
Length = len[0] | ( len[1] << 8);
|
|
LoadPSHeader(buf,Opcode,Length,Param1);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, Length + PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0) {
|
|
return FALSE;
|
|
}
|
|
do {
|
|
plen = read(dd, buf, HCI_MAX_EVENT_SIZE);
|
|
if (plen < 0)
|
|
return FALSE;
|
|
} while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_PS);
|
|
memcpy((UCHAR *)out, buf + HCI_EVENT_HEADER_SIZE + 1, plen - HCI_EVENT_HEADER_SIZE - 1);
|
|
break;
|
|
}
|
|
|
|
case PS_WRITE:
|
|
for(i=0;i< Param1;i++){
|
|
LoadPSHeader(buf,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId);
|
|
for(j=0;j<PsTagEntry[i].TagLen;j++){
|
|
buf[4+j]=PsTagEntry[i].TagData[j];
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PsTagEntry[i].TagLen + PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0){
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PS_DYNMEM_OVERRIDE:
|
|
LoadPSHeader(buf,Opcode,RamDynMemOverride.Len,RamDynMemOverride.Len);
|
|
for(j=0;j<RamDynMemOverride.Len;j++){
|
|
buf[4+j]=RamDynMemOverride.Data[j];
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_PS,RamDynMemOverride.Len + PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0){
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case PS_VERIFY_CRC:
|
|
//printf("PSOperations - PS_VERIFY_CRC:VALUE of CRC:%d\r\n",Param1);
|
|
Length =0;
|
|
LoadPSHeader(buf,Opcode,Length,Param1);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0){
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case PS_GET_LENGTH: {
|
|
ssize_t plen = 0;
|
|
LoadPSHeader(buf,Opcode,0,Param1);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, PS_COMMAND_HEADER, buf);
|
|
if(buf[iRet-1] != 0){
|
|
return FALSE;
|
|
}
|
|
do {
|
|
plen = read(dd, buf, HCI_MAX_EVENT_SIZE);
|
|
if (plen < 0)
|
|
return FALSE;
|
|
} while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_PS);
|
|
*((UINT16 *)out) = (buf[HCI_EVENT_HEADER_SIZE + 2] << 8) | buf[HCI_EVENT_HEADER_SIZE + 1];
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#if 0
|
|
static int GetDeviceType(int dd){
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int iRet;
|
|
unsigned int Reg = 0;
|
|
|
|
memset(&buf,0,sizeof(buf));
|
|
buf[0] = (FPGA_REGISTER & 0xFF);
|
|
buf[1] = ((FPGA_REGISTER >> 8) & 0xFF);
|
|
buf[2] = ((FPGA_REGISTER >> 16) & 0xFF);
|
|
buf[3] = ((FPGA_REGISTER >> 24) & 0xFF);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY,4, buf);
|
|
if(buf[6] != 0){
|
|
return FALSE;
|
|
}
|
|
|
|
Reg = buf[10];
|
|
Reg = ((Reg << 8) | buf[9]);
|
|
Reg = ((Reg << 8) | buf[8]);
|
|
Reg = ((Reg << 8) | buf[7]);
|
|
return Reg;
|
|
}
|
|
#endif
|
|
|
|
/* PS Operations */
|
|
static int PSInit(int dd){
|
|
int i,Crc=0,DevType =0;
|
|
BOOL BDADDR_Present = 0;
|
|
BOOL File_Present = 0;
|
|
|
|
//DevType = GetDeviceType(dd);
|
|
//printf("\nDevice Type:%x\n",DevType);
|
|
if(DevType){
|
|
if(DevType == 0xdeadc0de){
|
|
|
|
if(!LoadConfFile(PS_ASIC_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PS)){
|
|
printf("\nPlease copy PS file to :%s\n",PS_ASIC_FILENAME);
|
|
//return FALSE;
|
|
}
|
|
else
|
|
File_Present = 1;
|
|
}
|
|
else{
|
|
if(!LoadConfFile(PS_FPGA_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PS)){
|
|
printf("\nPlease copy PS file to :%s\n",PS_FPGA_FILENAME);
|
|
File_Present = 1;
|
|
//return FALSE;
|
|
}
|
|
else
|
|
File_Present = 1;
|
|
}
|
|
}
|
|
else{
|
|
if(!LoadConfFile(PS_ASIC_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PS)){
|
|
printf("\nPlease copy PS file to :%s\n",PS_ASIC_FILENAME);
|
|
File_Present = 1;
|
|
//return FALSE;
|
|
}
|
|
else
|
|
File_Present = 1;
|
|
}
|
|
|
|
if(!LoadConfFile(PATCH_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PATCH)){
|
|
printf("\nPlease copy Patch file to :%s\n",PATCH_FILENAME);
|
|
File_Present = 1;
|
|
}
|
|
else
|
|
File_Present = 1;
|
|
|
|
if(!File_Present){
|
|
printf("\nPS and Patch files are not present\n");
|
|
return FALSE;
|
|
}
|
|
if(Tag_Count == 0){
|
|
Total_tag_lenght = 10;
|
|
|
|
}
|
|
else{
|
|
for(i=0; i<Tag_Count; i++){
|
|
if(PsTagEntry[i].TagId == 1){
|
|
BDADDR_Present = TRUE;
|
|
//printf("ReadPSFiles - BD ADDR is present in Patch File \r\n");
|
|
}
|
|
|
|
if(PsTagEntry[i].TagLen % 2 == 1){
|
|
Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen + 1;
|
|
}
|
|
else{
|
|
Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if(Tag_Count > 0 && !BDADDR_Present){
|
|
//printf("\nReadPSFiles - BD ADDR is not present adding 10 extra bytes \r\n");
|
|
Total_tag_lenght=Total_tag_lenght + 10;
|
|
}
|
|
Total_tag_lenght = Total_tag_lenght+ 10 + (Tag_Count*4);
|
|
|
|
// printf("\nPSInitialize - PATCH:%d, DYN:%d, TAG:%d Total_tag_lenght:%d\n",Patch_Count,DynMem_Count,Tag_Count,Total_tag_lenght);
|
|
|
|
if(Patch_Count > 0)
|
|
Crc |= RAM_PATCH_REGION;
|
|
if(DynMem_Count)
|
|
Crc |= RAM_DYN_MEM_REGION;
|
|
if(Tag_Count > 0)
|
|
Crc |= RAM_PS_REGION;
|
|
|
|
if(Patch_Count || DynMem_Count || Tag_Count ){
|
|
if(Patch_Count > 0){
|
|
if(!PSOperations(dd,WRITE_PATCH,Patch_Count, NULL)){
|
|
printf("\nPSInitialize - *** WRITE_PATCH FAILED**** \r\n");
|
|
return FALSE;
|
|
}
|
|
if(!PSOperations(dd,ENABLE_PATCH,0, NULL)){
|
|
printf("\nPSInitialize - *** ENABLE_PATCH FAILED**** \r\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
if(DynMem_Count){
|
|
if(!PSOperations(dd,PS_DYNMEM_OVERRIDE,DynMem_Count, NULL)){
|
|
printf("\nPSInitialize - *** PS_DYNMEM_OVERRIDE FAILED**** \r\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
if(!PSOperations(dd,PS_RESET,Total_tag_lenght, NULL)){
|
|
printf("\nPSInitialize - *** PS RESET FAILED**** \r\n");
|
|
return FALSE;
|
|
}
|
|
if(Tag_Count > 0){
|
|
if(!PSOperations(dd,PS_WRITE,Tag_Count, NULL)){
|
|
printf("\nPSInitialize - *** PS_WRITE FAILED**** \r\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(!PSOperations(dd,PS_VERIFY_CRC,Crc, NULL)){
|
|
printf("\nVerify CRC failed\n");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
static int writeHciCommand(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, UCHAR *buf){
|
|
#ifdef DUMP_DEBUG
|
|
#define cmd_opcode_pack(ogf, ocf) (uint16_t)((ocf & 0x03ff)|(ogf << 10))
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
#define htobs(d) (d)
|
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
#define htobs(d) bswap_16(d);
|
|
#else
|
|
#error "Unknown byte order"
|
|
#endif
|
|
int i = 0, j = 0;
|
|
uint16_t opcode = htobs(cmd_opcode_pack(ogf, ocf));
|
|
|
|
printf("\nDump:\n");
|
|
printf("0x%02X ", opcode & 0xff);
|
|
i++;
|
|
printf("0x%02X ", (opcode & 0xff00) >> 8);
|
|
i++;
|
|
printf("0x%02X ", plen);
|
|
i++;
|
|
for (j = 0; j < plen; i++, j++) {
|
|
printf("0x%02X ", buf[j]);
|
|
if (((i+1) % 8) == 0 && i != 0)
|
|
printf("\n");
|
|
}
|
|
if (((i+1) % 8) != 0) printf("\n");
|
|
buf[6] = 0;
|
|
return plen;
|
|
#else
|
|
struct hci_filter flt;
|
|
uint16_t opcode, topcode;
|
|
|
|
/* Setup filter */
|
|
hci_filter_clear(&flt);
|
|
hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
|
|
hci_filter_all_events(&flt);
|
|
if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
|
|
perror("HCI filter setup failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
//printf("< HCI Command: ogf 0x%02x, ocf 0x%04x, plen %d\n", ogf, ocf, plen);
|
|
if (hci_send_cmd(dd, ogf, ocf, plen, buf) < 0) {
|
|
perror("Send failed");
|
|
hci_close_dev(dd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
sleep(0.4);
|
|
opcode = (ogf << 10 | ocf);
|
|
do {
|
|
plen = read(dd, buf,HCI_MAX_EVENT_SIZE);
|
|
if (plen < 0) {
|
|
perror("Read failed");
|
|
hci_close_dev(dd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
topcode=(uint16_t)(buf[4] | (buf[5] << 8));
|
|
}while(topcode != opcode);
|
|
return plen;
|
|
#endif
|
|
}
|
|
static int MemBlkRead(int dd,UINT32 Address,UCHAR *pBuffer, UINT32 Length){
|
|
UINT32 Size, ByteLeft,IntCnt;
|
|
UCHAR *pData,*pTemp=pBuffer;
|
|
int iRet;
|
|
int TempVal;
|
|
|
|
IntCnt =0;
|
|
TempVal = (Length % 4);
|
|
if (TempVal !=0)
|
|
{
|
|
Length = Length + (4- (Length%4));
|
|
}
|
|
ByteLeft = Length;
|
|
while (ByteLeft > 0)
|
|
{
|
|
Size = (ByteLeft > MEM_BLK_DATA_MAX) ? MEM_BLK_DATA_MAX : ByteLeft;
|
|
// printf("\nMemBlkwrite : Size :%x Address :%x\n",Size, Address);
|
|
pData = (UCHAR *) malloc(Size + 6);
|
|
pData[0]= 0x00;//depot/esw/projects/azure/AR3001_3_0/src/hci/Hci_Vsc_Proc.c
|
|
pData[1]= (Address & 0xFF);
|
|
pData[2]= ((Address >> 8) & 0xFF);
|
|
pData[3]= ((Address >> 16) & 0xFF);
|
|
pData[4]= ((Address >> 24) & 0xFF);
|
|
pData[5]= Size;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,6,pData);
|
|
if(pData[6]!= 0){
|
|
printf("\nwrite memory command failed due to reason 0x%X\n",pData[6]);
|
|
free(pData);
|
|
return FALSE;
|
|
}
|
|
if ((read(dd, pData,HCI_MAX_EVENT_SIZE)) < 0) {
|
|
perror("Read failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if(pData[3]!=3) {
|
|
perror("Read failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
memcpy(pTemp,(pData+4),Size);
|
|
pTemp+=Size;
|
|
IntCnt = Size;
|
|
ByteLeft -= Size;
|
|
Address += Size;
|
|
free(pData);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static int MemBlkwrite(int dd,UINT32 Address,UCHAR *pBuffer, UINT32 Length){
|
|
UINT32 Size, ByteLeft,IntCnt;
|
|
UCHAR *pData;
|
|
int iRet;
|
|
ByteLeft = Length;
|
|
IntCnt =0;
|
|
while (ByteLeft > 0)
|
|
{
|
|
|
|
Size = (ByteLeft > MEM_BLK_DATA_MAX) ? MEM_BLK_DATA_MAX : ByteLeft;
|
|
// printf("\nMemBlkwrite : Size :%x Address :%x\n",Size, Address);
|
|
pData = (UCHAR *) malloc(Size + 6);
|
|
pData[0]= 0x01;
|
|
pData[1]= (Address & 0xFF);
|
|
pData[2]= ((Address >> 8) & 0xFF);
|
|
pData[3]= ((Address >> 16) & 0xFF);
|
|
pData[4]= ((Address >> 24) & 0xFF);
|
|
pData[5]= Size;
|
|
memcpy(&pData[6],&pBuffer[IntCnt],Size);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,Size+6,pData);
|
|
if(pData[6]!= 0){
|
|
printf("\nwrite memory command faileddue to reason 0x%X\n",pData[6]);
|
|
free(pData);
|
|
return FALSE;
|
|
}
|
|
IntCnt = Size;
|
|
ByteLeft -= Size;
|
|
Address += Size;
|
|
free(pData);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static int Dut(int dd){
|
|
int iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 3; //All scan enabled
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite scan mode command failed due to reason 0x%X\n",buf[6]);
|
|
return FALSE;
|
|
}
|
|
sleep(1);
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = writeHciCommand(dd, OGF_TEST_CMD, OCF_ENABLE_DEVICE_UNDER_TEST_MODE, 0, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nDUT mode command failed due to reason 0x%X\n",buf[6]);
|
|
return FALSE;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0; //SEQN Track enable =0
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_TEST_MODE_SEQN_TRACKING , 1, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nTest Mode seqn Tracking failed due to reason 0x%X\n",buf[6]);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void Audio_DumpStats(tAudioStat *AudioStats)
|
|
{
|
|
printf("\n\n");
|
|
printf(" Audio Statistics\n");
|
|
printf(">RxCmplt: %d\n",AudioStats->RxCmplt);
|
|
printf(">TxCmplt: %d\n",AudioStats->TxCmplt);
|
|
printf(">RxSilenceInsert: %d\n",AudioStats->RxSilenceInsert);
|
|
printf(">RxAirPktDump: %d\n",AudioStats->RxAirPktDump);
|
|
printf(">MaxPLCGenInterval: %d\n",AudioStats->MaxPLCGenInterval);
|
|
printf(">RxAirPktStatusGood: %d\n",AudioStats->RxAirPktStatusGood);
|
|
printf(">RxAirPktStatusError: %d\n",AudioStats->RxAirPktStatusError);
|
|
printf(">RxAirPktStatusLost: %d\n",AudioStats->RxAirPktStatusLost);
|
|
printf(">RxAirPktStatusPartial: %d\n",AudioStats->RxAirPktStatusPartial);
|
|
printf(">SampleMin: %d\n",AudioStats->SampleMin);
|
|
printf(">SampleMax: %d\n",AudioStats->SampleMax);
|
|
printf(">SampleCounter: %d\n",AudioStats->SampleCounter);
|
|
printf("\n\n");
|
|
|
|
memset((UCHAR *)AudioStats, 0, sizeof(tAudioStat));
|
|
AudioStats->SampleMax =SHRT_MIN;
|
|
AudioStats->SampleMin =SHRT_MAX;
|
|
}
|
|
|
|
static int ReadAudioStats(int dd){
|
|
|
|
tBtHostInterest HostInt;
|
|
tAudioStat Stats;
|
|
|
|
ReadHostInterest(dd, &HostInt);
|
|
if(!HostInt.AudioStatAddr || (HostInt.Version < 0x0300)){
|
|
printf("\nAudio Stat not present\n");
|
|
return FALSE;
|
|
}
|
|
ReadMemoryBlock(dd,HostInt.AudioStatAddr,(UCHAR *)&Stats,sizeof(tAudioStat));
|
|
Audio_DumpStats(&Stats);
|
|
return TRUE;
|
|
}
|
|
|
|
void BRM_DumpStats(tBRM_Stats *Stats)
|
|
{
|
|
printf("\n Link Controller Voice DMA Statistics\n");
|
|
printf(" %22s: %u\n", "VoiceTxDmaIntrs", Stats->VoiceTxDmaIntrs);
|
|
printf(" %22s: %u\n", "VoiceTxPktAvail", Stats->VoiceTxPktAvail);
|
|
printf(" %22s: %u\n", "VoiceTxPktDumped", Stats->VoiceTxPktDumped);
|
|
printf(" %22s: %u\n", "VoiceTxErrors", Stats->VoiceTxErrorIntrs);
|
|
printf(" %22s: %u\n", "VoiceTxDmaErrors", Stats->VoiceTxDmaErrorIntrs);
|
|
printf(" %22s: %u\n", "VoiceTxSilenceInserts", Stats->VoiceTxDmaSilenceInserts);
|
|
printf("\n");
|
|
printf(" %22s: %u\n", "VoiceRxDmaIntrs", Stats->VoiceRxDmaIntrs);
|
|
printf(" %22s: %u\n", "VoiceRxGoodPkts", Stats->VoiceRxGoodPkts);
|
|
printf(" %22s: %u\n", "VoiceRxPktDumped", Stats->VoiceRxPktDumped);
|
|
printf(" %22s: %u\n", "VoiceRxErrors", Stats->VoiceRxErrorIntrs);
|
|
printf(" %22s: %u\n", "VoiceRxCRC", Stats->VoiceRxErrCrc);
|
|
printf(" %22s: %u\n", "VoiceRxUnderOverFlow", Stats->VoiceRxErrUnderOverFlow);
|
|
printf("\n");
|
|
printf(" %22s: %u\n", "SchedOnVoiceError", Stats->SchedOnVoiceError);
|
|
printf(" %22s: %u\n", "VoiceTxReapOnError", Stats->VoiceTxReapOnError);
|
|
printf(" %22s: %u\n", "VoiceRxReapOnError", Stats->VoiceRxReapOnError);
|
|
printf(" %22s: %u\n", "VoiceSchedulingError", Stats->VoiceSchedulingError);
|
|
|
|
printf("\n Link Controller ACL DMA Statistics\n");
|
|
printf(" %22s: %u\n", "DmaIntrs", Stats->DmaIntrs);
|
|
printf(" %22s: %u\n", "ErrWrongLlid", Stats->ErrWrongLlid);
|
|
printf(" %22s: %u\n", "ErrL2CapLen", Stats->ErrL2CapLen);
|
|
printf(" %22s: %u\n", "ErrUnderOverFlow", Stats->ErrUnderOverFlow);
|
|
printf(" %22s: %u\n", "RxBufferDumped", Stats->RxBufferDumped);
|
|
printf(" %22s: %u\n", "ErrWrongLmpPktType", Stats->ErrWrongLmpPktType);
|
|
printf(" %22s: %u\n", "ErrWrongL2CapPktType", Stats->ErrWrongL2CapPktType);
|
|
printf(" %22s: %u\n", "IgnoredPkts", Stats->IgnoredPkts);
|
|
printf("\n");
|
|
printf(" %22s: %u\n", "Data TxBuffers", Stats->DataTxBuffers);
|
|
printf(" %22s: %u\n", "Data RxBuffers", Stats->DataRxBuffers);
|
|
printf(" %22s: %u\n", "LMP TxBuffers", Stats->LmpTxBuffers);
|
|
printf(" %22s: %u\n", "LMP RxBuffers", Stats->LmpRxBuffers);
|
|
printf(" %22s: %u\n", "HEC Errors", Stats->HecFailPkts);
|
|
printf(" %22s: %u\n", "CRC Errors", Stats->CrcFailPkts);
|
|
|
|
// Buffer Management
|
|
printf("\n Buffer Management Statistics\n");
|
|
printf(" %22s: %u\n", "CtrlErrNoLmpBufs", Stats->CtrlErrNoLmpBufs);
|
|
|
|
printf("\n Sniff Statistics\n");
|
|
printf(" %22s: %u\n", "SniffSchedulingError", Stats->SniffSchedulingError);
|
|
printf(" %22s: %u\n", "SniffIntervalNoCorr", Stats->SniffIntervalNoCorr);
|
|
|
|
// Other stats
|
|
printf("\n Other Statistics\n");
|
|
printf(" %22s: %u\n", "ForceOverQosJob", Stats->ForceOverQosJob);
|
|
//printf(" %22s: %u\n", "Temp 1", Stats->Temp1);
|
|
//printf(" %22s: %u\n", "Temp 2", Stats->Temp2);
|
|
|
|
// Test Mode Stats
|
|
printf("\n Test Mode Statistics\n");
|
|
printf(" %22s: %u\n", "TestModeDroppedTxPkts", Stats->TestModeDroppedTxPkts);
|
|
printf(" %22s: %u\n", "TestModeDroppedLmps", Stats->TestModeDroppedLmps);
|
|
|
|
// Error Stats
|
|
printf("\n General Error Statistics\n");
|
|
printf(" %22s: %u\n", "TimePassedIntrs", Stats->TimePassedIntrs);
|
|
printf(" %22s: %u\n", "NoCommandIntrs", Stats->NoCommandIntrs);
|
|
}
|
|
|
|
static int ReadGlobalDMAStats(int dd){
|
|
tBtHostInterest HostInt;
|
|
tBRM_Stats Stats;
|
|
|
|
ReadHostInterest(dd, &HostInt);
|
|
if(!HostInt.GlobalDmaStats || (HostInt.Version < 0x0100)){
|
|
printf("\nGlobal DMA stats not present\n");
|
|
return FALSE;
|
|
}
|
|
ReadMemoryBlock(dd,HostInt.GlobalDmaStats,(UCHAR *)&Stats,sizeof(tBRM_Stats));
|
|
BRM_DumpStats(&Stats);
|
|
return TRUE;
|
|
}
|
|
|
|
static int ResetGlobalDMAStats(int dd){
|
|
tBtHostInterest HostInt;
|
|
tBRM_Stats Stats;
|
|
|
|
ReadHostInterest(dd, &HostInt);
|
|
if(!HostInt.GlobalDmaStats || (HostInt.Version < 0x0100)){
|
|
printf("\nGlobal DMA stats not present\n");
|
|
return FALSE;
|
|
}
|
|
memset(&Stats,0,sizeof(Stats));
|
|
printf("\nHarry\n");
|
|
WriteMemoryBlock(dd,HostInt.GlobalDmaStats,(UCHAR *)&Stats,sizeof(tBRM_Stats));
|
|
printf("\nDMA stattestics has been reset\n");
|
|
return TRUE;
|
|
}
|
|
|
|
static int ReadTpcTable(int dd){
|
|
tBtHostInterest HostInt;
|
|
tPsSysCfgTransmitPowerControlTable TpcTable;
|
|
int i;
|
|
|
|
ReadHostInterest(dd, &HostInt);
|
|
if(!HostInt.TpcTableAddr || (HostInt.Version < 0x0100)){
|
|
printf("\nTPC table not present\n");
|
|
return FALSE;
|
|
}
|
|
ReadMemoryBlock(dd,HostInt.TpcTableAddr,(UCHAR *)&TpcTable,sizeof(TpcTable));
|
|
for(i=0;i< TpcTable.NumOfEntries; i++){
|
|
printf("Level [%d] represents %3d dBm\n",i,TpcTable.t[i].TxPowerLevel);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
static void dump_conf_data(){
|
|
printf("\nTAG_COUNT %d\n",Tag_Count);
|
|
int i=0,j=0;
|
|
for(i=0;i<Tag_Count;i++){
|
|
printf("\nTAG ID :%X LEN:%X\n",PsTagEntry[i].TagId,PsTagEntry[i].TagLen);
|
|
for(j=0;j<PsTagEntry[i].TagLen;j++)
|
|
printf("\t %x",PsTagEntry[i].TagData[j]);
|
|
}
|
|
printf("\n");
|
|
printf("\nPATCH_COUNT %d\n",Patch_Count);
|
|
for(i=0;i<Patch_Count;i++){
|
|
printf("\tPATCH LEN:%X\t",RamPatch[i].Len);
|
|
for(j=0;j<RamPatch[i].Len;j++)
|
|
printf("\t %x",RamPatch[i].Data[j]);
|
|
}
|
|
printf("\n");
|
|
|
|
printf("\tDYMA LEN:%X\t",RamDynMemOverride.Len);
|
|
for(j=0;j<RamDynMemOverride.Len;j++)
|
|
printf("\t %x",RamDynMemOverride.Data[j]);
|
|
printf("\n");
|
|
|
|
}
|
|
*/
|
|
static const char *psreset_help =
|
|
"Usage:\n"
|
|
"\n psreset\n";
|
|
|
|
static void cmd_psreset(int dev_id, int argc, char **argv){
|
|
int dd,Length =0,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if(argc > 1){
|
|
printf("\n%s\n",psreset_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
PSInit(dd);
|
|
memset(&buf,0,sizeof(buf));
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,Length,buf);
|
|
if(buf[6] != 0){
|
|
printf("\nError: HCI RESET failed due to reason 0x%X\n",buf[6]);
|
|
return;
|
|
}
|
|
|
|
// Bttest work around for external 32k
|
|
|
|
|
|
int IsForeverRepeat=0;
|
|
int IsCmdIdle=0;
|
|
int address=0, width = 0, value=0;
|
|
int loop=0,Reg=0;
|
|
do
|
|
{
|
|
|
|
address = 0x00020024;
|
|
width = 4;
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = (UCHAR)width; //Memory width
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
value = buf[10];
|
|
value = ((value << 8) | buf[9]);
|
|
value = ((value << 8) | buf[8]);
|
|
value = ((value << 8) | buf[7]);
|
|
|
|
|
|
if(value&0x40000000)
|
|
IsForeverRepeat=1;
|
|
else
|
|
IsForeverRepeat=0;
|
|
|
|
|
|
address = 0x00020020;
|
|
width = 4;
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = (UCHAR)width; //Memory width
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
value = buf[10];
|
|
value = ((value << 8) | buf[9]);
|
|
value = ((value << 8) | buf[8]);
|
|
value = ((value << 8) | buf[7]);
|
|
|
|
if((value&0x0000000f)==0x8)
|
|
IsCmdIdle=1;
|
|
else
|
|
IsCmdIdle=0;
|
|
|
|
}
|
|
while(!(IsForeverRepeat&IsCmdIdle));//Wait til brm issues forever idle
|
|
|
|
|
|
address = 0x000200a8;
|
|
width = 4;
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = (UCHAR)width; //Memory width
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
value = buf[10];
|
|
value = ((value << 8) | buf[9]);
|
|
value = ((value << 8) | buf[8]);
|
|
value = ((value << 8) | buf[7]);
|
|
|
|
|
|
value |= 0x1;
|
|
|
|
loop = 0;
|
|
while ( loop < 10 ) {
|
|
|
|
loop++;
|
|
|
|
address = 0x000200a8;
|
|
width = 4;
|
|
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = width; //Memory width
|
|
buf[5] = (value & 0xFF);
|
|
buf[6] = ((value >> 8) & 0xFF);
|
|
buf[7] = ((value >> 16) & 0xFF);
|
|
buf[8] = ((value >> 24) & 0xFF);
|
|
buf[9] = 0xFF;
|
|
buf[10] = 0xFF;
|
|
buf[11] = 0xFF;
|
|
buf[12] = 0xFF;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
address = 0x00004064;
|
|
width = 4;
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = (UCHAR)width; //Memory width
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nRead Memory address failed\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
Reg = buf[10];
|
|
Reg = ((Reg << 8) | buf[9]);
|
|
Reg = ((Reg << 8) | buf[8]);
|
|
Reg = ((Reg << 8) | buf[7]);
|
|
|
|
if(Reg & 0x04) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------
|
|
|
|
|
|
hci_close_dev(dd);
|
|
printf("\nReset Done\n");
|
|
}
|
|
static const char *reset_help =
|
|
"Usage:\n"
|
|
"\n reset\n";
|
|
|
|
static void cmd_reset(int dev_id, int argc, char **argv){
|
|
int dd,Length =0,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if(argc > 1) {
|
|
printf("\n%s\n",reset_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,sizeof(buf));
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,Length,buf);
|
|
if(buf[6] != 0){
|
|
printf("\nError: HCI RESET failed due to reason 0x%X\n",buf[6]);
|
|
return;
|
|
}
|
|
|
|
hci_close_dev(dd);
|
|
printf("\nReset Done\n");
|
|
}
|
|
static const char *rba_help =
|
|
"Usage:\n"
|
|
"\n rba\n";
|
|
|
|
static void cmd_rba(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if(argc > 1){
|
|
printf("\n%s\n",rba_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nread bdaddr command failed due to reason 0x%X\n",buf[6] );
|
|
return;
|
|
}
|
|
printf("\nBD ADDRESS: \n");
|
|
int i;
|
|
for(i=iRet-1;i > 7;i--){
|
|
printf("%02X:",buf[i]);
|
|
}
|
|
printf("%X \n\n",buf[7]);
|
|
hci_close_dev(dd);
|
|
|
|
}
|
|
|
|
static const char *dtx_help =
|
|
"Usage:\n"
|
|
"\n dtx\n";
|
|
|
|
static void cmd_dtx(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if(argc > 1){
|
|
printf("\n%s\n",dtx_help);
|
|
return;
|
|
}
|
|
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_DISABLE_TX, 0, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nDisable TX command failed due to reason 0x%X\n",buf[6]);
|
|
return;
|
|
}
|
|
else {
|
|
printf("\nDisable TX command passed\n");
|
|
}
|
|
hci_close_dev(dd);
|
|
|
|
}
|
|
|
|
static const char *ssm_help =
|
|
"Usage:\n"
|
|
"\n ssm [0|1]\n"
|
|
"\nExample:\n"
|
|
"\tssm 0\t(Sleep disabled)\n"
|
|
"\tssm 1\t(Sleep enabled)\n";
|
|
|
|
static void cmd_ssm(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if(argc != 2){
|
|
printf("\n%s\n",ssm_help);
|
|
return;
|
|
}
|
|
|
|
if(atoi(argv[1]) > 1){
|
|
printf("\nInvalid sleep mode :%d\n",atoi(argv[1]));
|
|
return;
|
|
}
|
|
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = atoi(argv[1]);;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_SLEEP_MODE, 1, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nSet sleep mode command failed due to reason 0x%X\n",buf[6]);
|
|
return;
|
|
}
|
|
else {
|
|
printf("\nSet sleep mode command passed\n");
|
|
}
|
|
hci_close_dev(dd);
|
|
|
|
}
|
|
|
|
static const char *wba_help =
|
|
"Usage:\n"
|
|
"\n wba <bdaddr>\n"
|
|
"\nExample:\n"
|
|
"\n wba 00:03:ff:56:23:89\n";
|
|
|
|
static void cmd_wba(int dev_id, int argc, char **argv){
|
|
//printf("\nFeature not implemented\n");
|
|
int dd,iRet;
|
|
bdaddr_t bdaddr;
|
|
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
if(argc < 2){
|
|
printf("\n%s\n",wba_help);
|
|
return;
|
|
}
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
str2ba(argv[1],&bdaddr);
|
|
if((strlen(argv[1]) < 17)||(strlen(argv[1]) > 17)){
|
|
printf("\nInvalid BD address : %s\n",argv[1]);
|
|
printf("\n%s\n",wba_help);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
LoadPSHeader(buf,PS_WRITE,BD_ADDR_SIZE,BD_ADDR_PSTAG);
|
|
int i,j=0;
|
|
for(i= 0,j=4;i< BD_ADDR_SIZE;i++,j++){
|
|
buf[j] = bdaddr.b[i];
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,BD_ADDR_SIZE + PS_COMMAND_HEADER, buf);
|
|
if(buf[6] != 0){
|
|
printf("\n Write BD address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
memset(&buf,0,sizeof(buf));
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,0,buf);
|
|
if(buf[iRet-1] != 0){
|
|
printf("\nError: HCI RESET failed\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
memset(&buf,0,sizeof(buf));
|
|
iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nread bdaddr command failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nBD address changed successfully\n");
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *edutm_help =
|
|
"Usage:\n"
|
|
"\n edutm\n";
|
|
|
|
static void cmd_edutm(int dev_id, int argc, char **argv){
|
|
int Crc = 0;
|
|
int dd;
|
|
//UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
UCHAR ZeroBuf[MEM_BLK_DATA_MAX*2] = {0};
|
|
if(argc > 1){
|
|
printf("\n%s\n",edutm_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
/*
|
|
Patch_Count = 20;
|
|
for(i=0; i < Patch_Count; i++){
|
|
RamPatch[i].Len = MAX_BYTE_LENGTH;
|
|
memset(&RamPatch[i].Data,0,MAX_BYTE_LENGTH);
|
|
}
|
|
printf("\nCMD DUT MODE\n");
|
|
*/
|
|
//When Patch file is present write the patch, if not present just enter DUT mode
|
|
if(!LoadConfFile(TESTPATCH_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PATCH)){
|
|
if(!Dut(dd)){
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nDevice is in test mode ...\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
//dump_conf_data();
|
|
Crc |= RAM_PATCH_REGION;
|
|
if(!MemBlkwrite(dd,(UINT32)MC_BCAM_COMPARE_ADDRESS, ZeroBuf, HCI_3_PATCH_SPACE_LENGTH_1)){
|
|
printf("\nError in clearing the patch space 1\n");
|
|
return;
|
|
}
|
|
|
|
if(!MemBlkwrite(dd,(UINT32)MC_BCAM_VALID_ADDRESS, ZeroBuf, HCI_3_PATCH_SPACE_LENGTH_1)){
|
|
printf("\nError in clearing the patch space 2\n");
|
|
return;
|
|
}
|
|
printf("\nLoading Patch from file :%s\n",TESTPATCH_FILENAME);
|
|
if(!PSOperations(dd,WRITE_PATCH,Patch_Count, NULL)){
|
|
printf("EnterDUT_HCI_3 : patch write failed \r\n");
|
|
return;
|
|
}
|
|
if(!PSOperations(dd,ENABLE_PATCH,0, NULL)){
|
|
printf("EnterDUT_HCI_3 : patch enable failed \r\n");
|
|
return;
|
|
}
|
|
if(!PSOperations(dd,PS_VERIFY_CRC,Crc, NULL)){
|
|
printf("EnterDUT_HCI_3 : verify crc failed \r\n");
|
|
return;
|
|
}
|
|
if(!Dut(dd)){
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nDevice is in test mode ...\n");
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
|
|
static int ReadMemorySmallBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){
|
|
int iRet;
|
|
UCHAR *pData;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
pData = (UCHAR *) malloc(Length + 6);
|
|
memset(pData,0,Length+6);
|
|
pData[0]= 0x00; //Memory Read Opcode
|
|
pData[1]= (StartAddress & 0xFF);
|
|
pData[2]= ((StartAddress >> 8) & 0xFF);
|
|
pData[3]= ((StartAddress >> 16) & 0xFF);
|
|
pData[4]= ((StartAddress >> 24) & 0xFF);
|
|
pData[5]= Length;
|
|
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,Length+6,pData);
|
|
if(pData[6]!= 0){
|
|
printf("\nwrite memory command failed due to reason 0x%X\n",pData[6]);
|
|
free(pData);
|
|
return FALSE;
|
|
}
|
|
int plen =0;
|
|
do{
|
|
plen = read(dd, buf,HCI_MAX_EVENT_SIZE);
|
|
if (plen < 0) {
|
|
free(pData);
|
|
perror("Read failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_MEMBLK);
|
|
memcpy(pBufToWrite,(buf+HCI_EVENT_HEADER_SIZE+1),Length);
|
|
free(pData);
|
|
return TRUE;
|
|
}
|
|
|
|
static int ReadMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){
|
|
|
|
int ModResult,i;
|
|
|
|
if(Length > MEM_BLK_DATA_MAX){
|
|
ModResult = Length % MEM_BLK_DATA_MAX;
|
|
for(i=0;i < (Length - ModResult);i += MEM_BLK_DATA_MAX) {
|
|
ReadMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), MEM_BLK_DATA_MAX);
|
|
}
|
|
if(ModResult){
|
|
ReadMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), ModResult);
|
|
}
|
|
}
|
|
else{
|
|
|
|
ReadMemorySmallBlock(dd, StartAddress, pBufToWrite, Length);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static int WriteMemorySmallBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){
|
|
int iRet;
|
|
UCHAR *pData;
|
|
|
|
printf("\nStart Address:%x Length:%x %x\n",StartAddress,Length,MEM_BLK_DATA_MAX);
|
|
/*if(Length <= MEM_BLK_DATA_MAX)
|
|
return FALSE; */
|
|
pData = (UCHAR *) malloc(Length + 6);
|
|
memset(pData,0,Length+6);
|
|
pData[0]= 0x01; //Write Read Opcode
|
|
pData[1]= (StartAddress & 0xFF);
|
|
pData[2]= ((StartAddress >> 8) & 0xFF);
|
|
pData[3]= ((StartAddress >> 16) & 0xFF);
|
|
pData[4]= ((StartAddress >> 24) & 0xFF);
|
|
pData[5]= Length;
|
|
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,Length+6,pData);
|
|
if(pData[6]!= 0){
|
|
printf("\nwrite memory command failed due to reason 0x%X\n",pData[6]);
|
|
free(pData);
|
|
return FALSE;
|
|
}
|
|
free(pData);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static int WriteMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){
|
|
|
|
int ModResult,i;
|
|
|
|
if(Length > MEM_BLK_DATA_MAX){
|
|
ModResult = Length % MEM_BLK_DATA_MAX;
|
|
for(i=0;i < (Length - ModResult);i += MEM_BLK_DATA_MAX) {
|
|
WriteMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), MEM_BLK_DATA_MAX);
|
|
}
|
|
if(ModResult){
|
|
WriteMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), ModResult);
|
|
}
|
|
}
|
|
else{
|
|
|
|
WriteMemorySmallBlock(dd, StartAddress, pBufToWrite, Length);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static int ReadHostInterest(int dd,tBtHostInterest *pHostInt){
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int iRet;
|
|
int HostInterestAddress;
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_HOST_INTEREST, 0, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nhost interest command failed due to reason 0x%X\n",buf[6]);
|
|
return FALSE;
|
|
}
|
|
HostInterestAddress = buf[iRet-1];
|
|
HostInterestAddress = ((HostInterestAddress << 8)|buf[iRet-2]);
|
|
HostInterestAddress = ((HostInterestAddress << 8)|buf[iRet-3]);
|
|
HostInterestAddress = ((HostInterestAddress << 8)|buf[iRet-4]);
|
|
ReadMemoryBlock(dd, HostInterestAddress,(UCHAR*)pHostInt, sizeof(tBtHostInterest));
|
|
|
|
if(pHostInt->MagicNumber != HI_MAGIC_NUMBER){
|
|
if((pHostInt->MagicNumber != 0xFBAD)|| (pHostInt->Version != 0xDECA))
|
|
return 0;
|
|
}
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
static int contRxAtGivenChannel(int dd, UCHAR *pString){
|
|
int Address, Mask, Reg, RxFreq,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
//1. Disable all scans and set intervals and scan windows eually
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0; //All scan disabled
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite scan mode command failed due to reason 0x%X\n",buf[6]);
|
|
return 0;
|
|
}
|
|
short int inq_scan = 0x1000;
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = (inq_scan&0xFF);
|
|
buf[1] = ((inq_scan >> 8)& 0xFF);
|
|
buf[2] = (inq_scan&0xFF);
|
|
buf[3] = ((inq_scan >> 8)& 0xFF);
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_INQ_ACTIVITY, 4, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite inquiry scan activity command failed due to reason 0x%X\n",buf[6]);
|
|
return 0;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = (inq_scan&0xFF);
|
|
buf[1] = ((inq_scan >> 8)& 0xFF);
|
|
buf[2] = (inq_scan&0xFF);
|
|
buf[3] = ((inq_scan >> 8)& 0xFF);
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY, 4, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite page scan activity command failed due to reason 0x%X\n",buf[6]);
|
|
return 0;
|
|
}
|
|
//2. Disbable AGC
|
|
Address = LC_JTAG_MODEM_REGS_ADDRESS + AGC_BYPASS_ADDRESS;
|
|
Mask = AGC_BYPASS_ENABLE_MASK;
|
|
Reg = AGC_BYPASS_ENABLE_SET(1);
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = (Address & 0xFF);
|
|
buf[1] = ((Address >>8) & 0xFF);
|
|
buf[2] = ((Address>>16) & 0xFF);
|
|
buf[3] = ((Address>>24) & 0xFF);
|
|
buf[4] = 0x04; //Memory width
|
|
buf[5] = (Reg & 0xFF);
|
|
buf[6] = ((Reg >> 8) & 0xFF);
|
|
buf[7] = ((Reg >> 16) & 0xFF);
|
|
buf[8] = ((Reg >> 24) & 0xFF);
|
|
buf[9] = (Mask & 0xFF);
|
|
buf[10] = ((Mask >>8) & 0xFF);
|
|
buf[11] = ((Mask>>16) & 0xFF);
|
|
buf[12] = ((Mask>>24) & 0xFF);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite to AGC bypass register failed due to reason 0x%X\n",buf[6]);
|
|
return 0;
|
|
}
|
|
// 3. Disable frequency hoping and set rx frequency
|
|
|
|
RxFreq = (int)pString;
|
|
Address = LC_DEV_PARAM_CTL_ADDRESS;
|
|
Mask = LC_DEV_PARAM_CTL_FREQ_HOP_EN_MASK |
|
|
LC_DEV_PARAM_CTL_RX_FREQ_MASK |
|
|
LC_DEV_PARAM_CTL_WHITEN_EN_MASK;
|
|
Reg = LC_DEV_PARAM_CTL_RX_FREQ_SET(RxFreq);
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = (Address & 0xFF);
|
|
buf[1] = ((Address >>8) & 0xFF);
|
|
buf[2] = ((Address>>16) & 0xFF);
|
|
buf[3] = ((Address>>24) & 0xFF);
|
|
buf[4] = 0x04; //Memory width
|
|
buf[5] = (Reg & 0xFF);
|
|
buf[6] = ((Reg >> 8) & 0xFF);
|
|
buf[7] = ((Reg >> 16) & 0xFF);
|
|
buf[8] = ((Reg >> 24) & 0xFF);
|
|
buf[9] = (Mask & 0xFF);
|
|
buf[10] = ((Mask >>8) & 0xFF);
|
|
buf[11] = ((Mask>>16) & 0xFF);
|
|
buf[12] = ((Mask>>24) & 0xFF);
|
|
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite to Rx Freq register failed due to reason 0x%X\n",buf[6]);
|
|
return 0;
|
|
}
|
|
// 4. Enable page scan only (Note: the old way puts device into inq scan mode only ???)
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 2; //Page scan enabled
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nPage scan enable command failed due to reason 0x%X\n",buf[6]);
|
|
return 0;
|
|
}
|
|
// 5. Increase correlator
|
|
Address = LC_JTAG_MODEM_REGS_ADDRESS + CORR_PARAM1_ADDRESS;
|
|
Mask = CORR_PARAM1_TIM_THR_MASK;
|
|
Reg = CORR_PARAM1_TIM_THR_SET(0x3f);
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = (Address & 0xFF);
|
|
buf[1] = ((Address >>8) & 0xFF);
|
|
buf[2] = ((Address>>16) & 0xFF);
|
|
buf[3] = ((Address>>24) & 0xFF);
|
|
buf[4] = 0x04; //Memory width
|
|
buf[5] = (Reg & 0xFF);
|
|
buf[6] = ((Reg >> 8) & 0xFF);
|
|
buf[7] = ((Reg >> 16) & 0xFF);
|
|
buf[8] = ((Reg >> 24) & 0xFF);
|
|
buf[9] = (Mask & 0xFF);
|
|
buf[10] = ((Mask >>8) & 0xFF);
|
|
buf[11] = ((Mask>>16) & 0xFF);
|
|
buf[12] = ((Mask>>24) & 0xFF);
|
|
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 12, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite to Correlator register failed due to reason 0x%X\n",buf[6]);
|
|
return 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
static const char *cwrx_help =
|
|
"Usage:\n"
|
|
"\n cwrx <Channel>\n";
|
|
|
|
static void cmd_cwrx(int dev_id, int argc, char **argv){
|
|
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
UCHAR channel;
|
|
BOOL Ok = TRUE;
|
|
if(argc != 2){
|
|
printf("\n%s\n",cwrx_help);
|
|
return;
|
|
}
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
channel = atoi(argv[1]);
|
|
if(channel > 78 || channel < 0){
|
|
printf("\nPlease enter channel 0-78!\n");
|
|
return;
|
|
}
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
// Disable sleep mode
|
|
memset(&buf,0,sizeof(buf));
|
|
buf[0] = 0;
|
|
iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_SLEEP_MODE,1,buf);
|
|
if(buf[6] != 0){
|
|
printf("\nError: Sleep mode failed due to reason 0x%X\n",buf[6]);
|
|
Ok = 0;
|
|
}
|
|
printf (" Continuoux Rx at channel %d\n",channel);
|
|
Ok = contRxAtGivenChannel(dd, &channel);
|
|
|
|
// All modes come here
|
|
if (Ok)
|
|
{
|
|
printf (" Continuoux Rx at channel %d Done...\n",channel);
|
|
}
|
|
else
|
|
{
|
|
printf ("\nERROR ---> Could not enter continuous Rx mode\n");
|
|
}
|
|
|
|
hci_close_dev(dd);
|
|
}
|
|
static const char *mb_help =
|
|
"Usage:\n"
|
|
"\n mb\n";
|
|
|
|
static void cmd_mb(int dev_id, int argc, char **argv){
|
|
|
|
int dd,iRet;
|
|
int InChar;
|
|
int FieldNum;
|
|
bdaddr_t bdaddr;
|
|
tBRM_Control_packet MasterBlaster;
|
|
UCHAR SkipRxSlot;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
char FieldAlias;
|
|
BOOL TestEnabled = 0,Ok = TRUE;
|
|
UINT8 setContTxType;
|
|
tBtHostInterest HostInt;
|
|
int address,width,value,mask;
|
|
if(argc > 1) {
|
|
printf("\n%s\n",mb_help);
|
|
return;
|
|
}
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nread bdaddr command failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
int i,j;
|
|
char bda[18];
|
|
for (i=iRet-1,j=0;i>7;i--,j+=3) {
|
|
sprintf(&bda[j],"%X",((buf[i]>>4)&0xFF));
|
|
sprintf(&bda[j+1],"%X",(buf[i]&0x0F));
|
|
sprintf(&bda[j+2],":");
|
|
}
|
|
sprintf(&bda[15],"%X",((buf[7]>>4)&0xFF));
|
|
sprintf(&bda[16],"%X",(buf[7]&0x0F));
|
|
bda[18] ='\0';
|
|
str2ba(bda,&bdaddr);
|
|
|
|
InitMasterBlaster(&MasterBlaster, &bdaddr, &SkipRxSlot);
|
|
#ifndef DUMP_DEBUG
|
|
Ok = ReadHostInterest(dd,&HostInt);
|
|
if(Ok) {
|
|
if (HostInt.TpcTableAddr && (HostInt.Version >= 0x0100)) {
|
|
Ok = ReadMemoryBlock(dd, HostInt.TpcTableAddr, (UCHAR *)&TpcTable, sizeof(TpcTable));
|
|
MasterBlaster.testCtrl.Power = TpcTable.NumOfEntries - 1;
|
|
}
|
|
}
|
|
if(!Ok) {
|
|
printf ("\nCould not load TPC table.\n");
|
|
sleep (2);
|
|
Ok = TRUE;
|
|
}
|
|
#endif
|
|
|
|
PrintMasterBlasterMenu (&MasterBlaster);
|
|
while (1) {
|
|
InChar = getchar();
|
|
FieldAlias = (char)InChar;
|
|
FieldNum = CheckField(MasterBlaster, &FieldAlias);
|
|
if (FieldNum == INVALID_MASTERBLASTER_FIELD) {
|
|
printf ("\nERROR ---> Invalid command. Try again.\n");
|
|
printf ("mb>");
|
|
getchar();
|
|
continue;
|
|
}
|
|
|
|
if (!strncmp(&FieldAlias, MasterBlasterMenu[EXX].Alias, 1)) {
|
|
printf("\nExit the Master Blaster Mode without reset\n");
|
|
break;
|
|
}
|
|
// If test has been enabled and the key is not 'e', send reset to stop the test
|
|
if (((TestEnabled == MB_RX_TEST) && strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1))
|
|
|| ((TestEnabled == MB_TX_TEST) && strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1))
|
|
|| ((TestEnabled == MB_CONT_RX_TEST || TestEnabled == MB_CONT_TX_TEST ||
|
|
TestEnabled == MB_LE_RX_TEST || TestEnabled == MB_LE_TX_TEST) &&
|
|
(strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)))) {
|
|
printf (" ... Please wait ...");
|
|
if (MasterBlaster.ContTxMode) {
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 255;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_CONT_TX_TESTER, 14, buf);
|
|
if(buf[6] != 0) {
|
|
printf("\nContinious Tx Tester command failed due to reason 0x%X\n",buf[6]);
|
|
Ok = 0;
|
|
} else
|
|
Ok = TRUE;
|
|
}
|
|
// Ok = Diag::Reset (Unit, "");
|
|
PSInit(dd);
|
|
memset(&buf,0,sizeof(buf));
|
|
iRet = writeHciCommand(dd,OGF_HOST_CTL,OCF_RESET,0,buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nError: HCI RESET failed due to reason 0x%X\n",buf[6]);
|
|
Ok = FALSE;
|
|
} else
|
|
Ok = TRUE;
|
|
if (!Ok) {
|
|
printf ("\nERROR ---> Could not stop test mode\n");
|
|
} else if (!strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1)
|
|
|| !strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1)
|
|
|| ((TestEnabled != MB_NO_TEST) &&
|
|
(!strncmp(&FieldAlias, MasterBlasterMenu[CR].Alias, 1) ||
|
|
!strncmp(&FieldAlias, MasterBlasterMenu[CT].Alias, 1) ||
|
|
!strncmp(&FieldAlias, MasterBlasterMenu[LR].Alias, 1) ||
|
|
!strncmp(&FieldAlias, MasterBlasterMenu[LT].Alias, 1))) ||
|
|
!strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)) {
|
|
TestEnabled = MB_NO_TEST;
|
|
}
|
|
sleep(1);
|
|
} if (!strncmp(&FieldAlias,MasterBlasterMenu[EX].Alias,1)) {
|
|
TestEnabled = MB_NO_TEST;
|
|
printf ("\n Exit ..\n");
|
|
break;
|
|
} else if (!strncmp(&FieldAlias,MasterBlasterMenu[ST].Alias,1)) {
|
|
TestEnabled = MB_NO_TEST;
|
|
getchar();
|
|
PrintMasterBlasterMenu (&MasterBlaster);
|
|
continue;
|
|
} else if (!strncmp(&FieldAlias,MasterBlasterMenu[GB].Alias,1)) {
|
|
memset(&buf,0,sizeof(buf));
|
|
buf[0] = MasterBlaster.BERType;
|
|
iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_GET_BERTYPE,0,buf);
|
|
if(buf[6] != 0) {
|
|
printf("Could not get BER info.\n");
|
|
} else {
|
|
int crcfail = buf[7] + (buf[8]<<8) + (buf[9]<<16) + (buf[10]<<24);
|
|
int total = buf[11] + (buf[12]<<8) + (buf[13]<<16) + (buf[14]<<24);
|
|
printf("\n\tCRCFail is %d, total is %d\n", crcfail, total);
|
|
}
|
|
|
|
|
|
} else if (!MasterBlasterMenu[FieldNum].pFunc (&MasterBlaster, MasterBlasterMenu[FieldNum].Options)) {
|
|
printf ("----%c\n", FieldAlias);
|
|
printf ("\nERROR ---> Invalid option. Try again.\n");
|
|
printf ("mb>");
|
|
getchar();
|
|
continue;
|
|
}
|
|
getchar();
|
|
PrintMasterBlasterMenu(&MasterBlaster);
|
|
|
|
// Enable TX test mode
|
|
if ((!strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1) && (TestEnabled == MB_NO_TEST))
|
|
|| (strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1) && (TestEnabled == MB_TX_TEST))) {
|
|
// Disable sleep mode
|
|
printf (".");
|
|
Ok = TRUE;
|
|
memset(&buf,0,sizeof(buf));
|
|
buf[0] = 0;
|
|
iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_SLEEP_MODE,1,buf);
|
|
if(buf[6] != 0) {
|
|
printf("\nError: Sleep mode failed due to reason 0x%X\n",buf[6]);
|
|
Ok = 0;
|
|
}
|
|
|
|
if (!Ok) {
|
|
printf ("\nERROR ---> Could not disable sleep mode\n");
|
|
printf ("mb>");
|
|
continue;
|
|
}
|
|
|
|
printf (".");
|
|
Ok = Dut(dd);
|
|
if (!Ok) {
|
|
printf("\nERROR ---> Could not enter DUT mode\n");
|
|
printf("mb>");
|
|
continue;
|
|
}
|
|
|
|
printf(".");
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = MasterBlaster.testCtrl.Mode ;
|
|
buf[1] = MasterBlaster.testCtrl.Packet;
|
|
buf[2] = MasterBlaster.testCtrl.DataLen & 0xFF;
|
|
buf[3] = ((MasterBlaster.testCtrl.DataLen>>8) & 0xFF);
|
|
buf[4] = MasterBlaster.testCtrl.HopMode;
|
|
buf[5] = MasterBlaster.testCtrl.TxFreq;
|
|
buf[6] = MasterBlaster.testCtrl.Power;
|
|
buf[7] = MasterBlaster.testCtrl.RxFreq;
|
|
buf[8] = MasterBlaster.bdaddr[0];
|
|
buf[9] = MasterBlaster.bdaddr[1];
|
|
buf[10] = MasterBlaster.bdaddr[2];
|
|
buf[11] = MasterBlaster.bdaddr[3];
|
|
buf[12] = MasterBlaster.bdaddr[4];
|
|
buf[13] = MasterBlaster.bdaddr[5];
|
|
buf[14] = SkipRxSlot;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_TX_TESTER, 15, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nContinious Tx Tester command failed due to reason 0x%X\n",buf[6]);
|
|
printf("\nERROR --> Could not enable master blaster mode\n");
|
|
TestEnabled = MB_NO_TEST;
|
|
Ok = 0;
|
|
} else {
|
|
printf(" test is in progress. Press 's' to stop the test\n");
|
|
TestEnabled = MB_TX_TEST;
|
|
}
|
|
printf("mb>");
|
|
continue;
|
|
} else if ((!strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1)) && TestEnabled == MB_TX_TEST) {
|
|
printf("test is in progress. Press 's' to stop the test\n");
|
|
printf("mb>");
|
|
continue;
|
|
}
|
|
|
|
/* Enable (LE) continuous tx/rx test modes */
|
|
if (((!strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)) && (TestEnabled == MB_NO_TEST))
|
|
|| (strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1) && (TestEnabled == MB_CONT_RX_TEST
|
|
|| TestEnabled == MB_CONT_TX_TEST || TestEnabled == MB_LE_RX_TEST || TestEnabled == MB_LE_TX_TEST))) {
|
|
// Disable sleep mode
|
|
printf (".");
|
|
Ok = TRUE;
|
|
memset(&buf,0,sizeof(buf));
|
|
buf[0] = 0;
|
|
iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_SLEEP_MODE,1,buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nError: Sleep mode failed due to reason 0x%X\n",buf[6]);
|
|
Ok = 0;
|
|
}
|
|
|
|
if (!Ok) {
|
|
printf ("\nERROR ---> Could not disable sleep mode\n");
|
|
printf ("mb>");
|
|
continue;
|
|
}
|
|
|
|
/* LE Rx Mode */
|
|
if (MasterBlaster.LERxMode == ENABLE) {
|
|
Ok = SU_LERxTest(dd, MasterBlaster.testCtrl.RxFreq);
|
|
TestEnabled = MB_LE_RX_TEST;
|
|
} else if (MasterBlaster.LETxMode == ENABLE) {
|
|
Ok = SU_LETxTest(dd, MasterBlaster.testCtrl.TxFreq, MasterBlaster.testCtrl.DataLen,
|
|
MasterBlaster.LETxParms.PktPayload);
|
|
TestEnabled = MB_LE_TX_TEST;
|
|
} else if (MasterBlaster.ContRxMode == ENABLE) {
|
|
UCHAR RxFreq = MasterBlaster.testCtrl.RxFreq;
|
|
Ok = contRxAtGivenChannel(dd, &RxFreq);
|
|
TestEnabled = MB_CONT_RX_TEST;
|
|
} else /* Continous TX mode */ {
|
|
printf(".");
|
|
Ok = Dut(dd);
|
|
if (!Ok) {
|
|
printf("\nERROR ---> Could not enter DUT mode\n");
|
|
printf("mb>");
|
|
continue;
|
|
}
|
|
/* Enable master blaster mode */
|
|
printf(".");
|
|
if (CW_Single_Tone == MasterBlaster.ContTxType)
|
|
setContTxType = Cont_Tx_Raw_1MHz;
|
|
else
|
|
setContTxType = MasterBlaster.ContTxType;
|
|
|
|
memset(&buf, 0, HCI_MAX_EVENT_SIZE);
|
|
buf[0] = MasterBlaster.testCtrl.Mode ;
|
|
buf[1] = MasterBlaster.testCtrl.Packet;
|
|
buf[2] = MasterBlaster.testCtrl.DataLen & 0xFF;
|
|
buf[3] = ((MasterBlaster.testCtrl.DataLen>>8) & 0xFF);
|
|
buf[4] = MasterBlaster.ContTxType;
|
|
buf[5] = MasterBlaster.testCtrl.TxFreq;
|
|
buf[6] = MasterBlaster.testCtrl.Power;
|
|
buf[7] = MasterBlaster.testCtrl.RxFreq;
|
|
buf[8] = MasterBlaster.bdaddr[0];
|
|
buf[9] = MasterBlaster.bdaddr[1];
|
|
buf[10] = MasterBlaster.bdaddr[2];
|
|
buf[11] = MasterBlaster.bdaddr[3];
|
|
buf[12] = MasterBlaster.bdaddr[4];
|
|
buf[13] = MasterBlaster.bdaddr[5];
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_CONT_TX_TESTER, 14, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nContinious Tx Tester command failed due to reason 0x%X\n",buf[6]);
|
|
Ok = FALSE;
|
|
} else
|
|
Ok = TRUE;
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
address = 0x00022914;
|
|
value = 0x00200000;
|
|
mask = 0x00200000;
|
|
width = 4;
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = width; //Memory width
|
|
buf[5] = (value & 0xFF);
|
|
buf[6] = ((value >> 8) & 0xFF);
|
|
buf[7] = ((value >> 16) & 0xFF);
|
|
buf[8] = ((value >> 24) & 0xFF);
|
|
buf[9] = (mask & 0xFF);
|
|
buf[10] = ((mask >>8) & 0xFF);
|
|
buf[11] = ((mask>>16) & 0xFF);
|
|
buf[12] = ((mask>>24) & 0xFF);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
Ok = FALSE;
|
|
} else
|
|
Ok = TRUE;
|
|
|
|
TestEnabled = MB_CONT_TX_TEST;
|
|
}
|
|
if (Ok) {
|
|
printf("Test is in progress. Press 's' to stop the test\n");
|
|
} else {
|
|
printf("\nERROR ---> Could not enable master blaster mode\n");
|
|
TestEnabled = MB_NO_TEST;
|
|
}
|
|
printf("mb>");
|
|
continue;
|
|
} else if ((!strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)) && TestEnabled) {
|
|
printf (" Test mode is in progress. Press 's' to stop the test\n");
|
|
printf ("mb>");
|
|
continue;
|
|
}
|
|
}
|
|
hci_close_dev(dd);
|
|
}
|
|
/*
|
|
static void cmd_gid(int dev_id, int argc, char **argv){
|
|
printf("\nFeature not implemented\n");
|
|
}
|
|
*/
|
|
static const char *wsm_help =
|
|
"Usage:\n"
|
|
"\n wsm [0|1|2|3]\n"
|
|
"\nExample:\n"
|
|
"\twsm 0\t(Scan disabled)\n"
|
|
"\twsm 1\t(Inquiry scan enabled)\n"
|
|
"\twsm 2\t(Page scan enabled)\n"
|
|
"\twsm 3\t(Inquiry and Page scan enabled)\n";
|
|
|
|
static void cmd_wsm(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
if(argc < 2){
|
|
printf("\n%s\n",wsm_help);
|
|
return;
|
|
}
|
|
if(atoi(argv[1]) > 3){
|
|
printf("\nInvalid scan mode :%d\n",atoi(argv[1]));
|
|
return;
|
|
}
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = atoi(argv[1]);
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite scan mode command failed due to reason 0x%X\n",buf[6]);
|
|
return;
|
|
}
|
|
hci_close_dev(dd);
|
|
printf("\nScan Mode set to :%d\n",atoi(argv[1]));
|
|
}
|
|
|
|
static void dumpHex(UCHAR *buf, int length, int col)
|
|
{
|
|
int i;
|
|
for (i = 0; i < length; i++) {
|
|
printf("0x%02x ", buf[i]);
|
|
if (((i+1) % col) == 0 && i != 0)
|
|
printf("\n");
|
|
}
|
|
if (((i+1) % col) != 0) printf("\n");
|
|
}
|
|
|
|
static void ReverseHexString(char *pStr)
|
|
{
|
|
int i, j;
|
|
char temp;
|
|
int len = strlen(pStr);
|
|
|
|
for (i = 0; pStr[i] == ' ' || pStr[i] == '\t'; i++);
|
|
|
|
if (pStr[i] == '0' && pStr[i+1] == 'x')
|
|
i += 2;
|
|
|
|
for (j = len - 1; i < j - 2; i += 2, j -= 2) {
|
|
temp = pStr[i];
|
|
pStr[i] = pStr[j - 1];
|
|
pStr[j - 1] = temp;
|
|
temp = pStr[i + 1];
|
|
pStr[i + 1] = pStr[j];
|
|
pStr[j] = temp;
|
|
}
|
|
}
|
|
|
|
static void GetByteSeq(UCHAR *pDst, UCHAR *pSrc, int Size)
|
|
{
|
|
UCHAR LowNibble, Nibble = 0;
|
|
UCHAR *pLastHex;
|
|
UCHAR *pStr = pSrc;
|
|
|
|
while (*pStr == ' ' || *pStr == '\t') pStr++;
|
|
|
|
if ((pStr[0] == '0') && (pStr[1] == 'x'))
|
|
pStr += 2;
|
|
|
|
pLastHex = pStr - 1;
|
|
while (IS_HEX(*(pLastHex + 1)))
|
|
pLastHex++;
|
|
|
|
LowNibble = 0;
|
|
|
|
while (Size > 0) {
|
|
if (pStr <= pLastHex) {
|
|
Nibble = CONV_HEX_DIGIT_TO_VALUE(*pStr);
|
|
pStr++;
|
|
} else {
|
|
Nibble = 0;
|
|
}
|
|
|
|
if (LowNibble) {
|
|
*pDst |= (UCHAR)(Nibble & 0x0F);
|
|
LowNibble = 0;
|
|
pDst++;
|
|
Size--;
|
|
} else {
|
|
*pDst = (UCHAR)((Nibble << 4) & 0xF0);
|
|
LowNibble = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned int GetUInt(char **ppLine, unsigned int DefaultValue)
|
|
{
|
|
char *pStr = *ppLine;
|
|
unsigned int Value = 0;
|
|
|
|
// Is it a hex value?
|
|
if ((*pStr == '0') && (*(pStr+1) == 'x'))
|
|
{
|
|
// We have a hex value
|
|
|
|
pStr += 2;
|
|
|
|
while (IS_HEX(*pStr))
|
|
{
|
|
Value = CONV_HEX_DIGIT_TO_VALUE(*pStr) + (Value*16);
|
|
pStr++;
|
|
}
|
|
|
|
}
|
|
else if (IS_DIGIT(*pStr))
|
|
{
|
|
// We have a decimal value
|
|
while (IS_DIGIT(*pStr))
|
|
{
|
|
Value = CONV_DEC_DIGIT_TO_VALUE(*pStr) + (Value*10);
|
|
pStr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We don't have a value at all - return default value
|
|
return DefaultValue;
|
|
}
|
|
|
|
// Update the BtString ptr
|
|
*ppLine = pStr;
|
|
return Value;
|
|
}
|
|
|
|
static const char *mbr_help =
|
|
"Usage:\n"
|
|
"\n mbr <address> <length> \n"
|
|
"\n Example \n"
|
|
"\n mbr 0x00004FFC 10 \n"
|
|
"\n mbr 0x00004FFC 0x10 \n";
|
|
|
|
static void cmd_mbr(int dev_id, int argc, char **argv){
|
|
int dd;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE*20];
|
|
|
|
if(argc != 3){
|
|
printf("\n%s\n",mbr_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
int length = GetUInt(&(argv[2]),0);
|
|
int address = GetUInt(&(argv[1]),0);
|
|
|
|
if ((address == 0) || (length==0)){
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE*20);
|
|
if(!MemBlkRead(dd,address,buf, length)) {
|
|
printf("\nmemory bulk read command failed\n");
|
|
return;
|
|
}
|
|
printf("\ndata: \n");
|
|
int i;
|
|
for(i=0;i < length;i+=4){
|
|
printf("%08X: ",address+i);
|
|
printf("%08X",*((int*)(buf+i)));
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
|
|
hci_close_dev(dd);
|
|
|
|
}
|
|
|
|
static const char *psr_help =
|
|
"Usage:\n"
|
|
"\n psr \n";
|
|
|
|
static void cmd_psr(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
if(argc > 1){
|
|
printf("\n%s\n",psr_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
LoadPSHeader(buf,PS_RESET,0,0);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER+2, buf);
|
|
if(buf[7] != 0){ /* Check for status */
|
|
printf("\n PS Reset failed\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
hci_close_dev(dd);
|
|
printf("PS reset done\n");
|
|
}
|
|
|
|
static const char *rpst_help =
|
|
"Usage:\n"
|
|
"\n rpst <tag id> <tag length> \n"
|
|
"\n Example:\n"
|
|
"\n rpst 1 6 \n";
|
|
static void cmd_rpst(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int tag_id,tag_len,i,j;
|
|
if(argc != 3){
|
|
printf("\n%s\n",rpst_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
tag_id = GetUInt(&(argv[1]),0);
|
|
tag_len = GetUInt(&(argv[2]),0);
|
|
LoadPSHeader(buf,PS_READ,tag_len,tag_id);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf);
|
|
if(buf[6] != 0){
|
|
printf("\n read PS tag failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = read(dd,&buf,HCI_MAX_EVENT_SIZE);
|
|
if(iRet < 0){
|
|
printf("\n read PS tag failed\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nTag ID :%X\nTag Length:%X\nTag Data:\n",tag_id,tag_len);
|
|
|
|
for(i=4,j=1;i<iRet;i++,j++){
|
|
printf("%02X ",buf[i]);
|
|
if(j%16 == 0)
|
|
printf("\n");
|
|
}
|
|
printf("\n\n");
|
|
hci_close_dev(dd);
|
|
}
|
|
static const char *wpst_help =
|
|
"Usage:\n"
|
|
"\n wpst <tag id> <tag length> <tag data>\n"
|
|
"\n Example:\n"
|
|
"\n wpst 1 6 00 03 F4 55 AB 77 \n";
|
|
|
|
static void cmd_wpst(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int tag_id,tag_len,i;
|
|
if(argc < 4){
|
|
printf("\n%s\n",wpst_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
tag_id = GetUInt(&(argv[1]),0);
|
|
tag_len = GetUInt(&(argv[2]),0);
|
|
if(argc < tag_len+3){
|
|
printf("\n Tag Data is less than Tag Length\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
LoadPSHeader(buf,PS_WRITE,tag_len,tag_id);
|
|
for(i=0;i<tag_len;i++){
|
|
buf[i+4] = strtol(argv[i+3], NULL, 16);
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER + tag_len, buf);
|
|
if(buf[6] != 0){
|
|
printf("\n Write PS tag failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *setam_help =
|
|
"Usage:\n"
|
|
"\nsetam <storage medium> <access mode>\n"
|
|
"\nstorage medium: 0-RAM 1-EEPROM\n"
|
|
"\naccess mode: 0-Read-only 1-Write-only 2-Read-Write 3- Disabled\n"
|
|
"\nExample:\n"
|
|
"\nsetam 0 3\n";
|
|
static void cmd_setam(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int medium,mode;
|
|
if(argc !=3){
|
|
printf("\n%s\n",setam_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
medium = GetUInt(&(argv[1]),0);
|
|
mode = GetUInt(&(argv[2]),0);
|
|
LoadPSHeader(buf,PS_SET_ACCESS_MODE,mode,medium);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nSet Access mode failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
hci_close_dev(dd);
|
|
printf("\nAccess mode changed successfully!\n");
|
|
}
|
|
|
|
static const char *setap_help =
|
|
"Usage:\n"
|
|
"\nsetap <storage medium> <priority>\n"
|
|
"\nstorage medium: 0-RAM 1-EEPROM\n"
|
|
"\npriority: #Highest number corresponds to highest priority\n"
|
|
"\nExample:\n"
|
|
"\nsetap 0 1\n";
|
|
|
|
static void cmd_setap(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int medium,priority;
|
|
if(argc !=3){
|
|
printf("\n%s\n",setap_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
medium = GetUInt(&(argv[1]),0);
|
|
priority = GetUInt(&(argv[2]),0);
|
|
LoadPSHeader(buf,PS_SET_ACCESS_MODE,priority,medium);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nSet Access priority failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
hci_close_dev(dd);
|
|
printf("\nPriority changed successfully!\n");
|
|
}
|
|
|
|
static const char *rpsraw_help =
|
|
"Usage:\n"
|
|
"\n rpsraw <offset> <length> \n"
|
|
"\n Example:\n"
|
|
"\n rpsraw 0x012c 10\n";
|
|
static void cmd_rpsraw(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int offset,len,i,j;
|
|
if(argc != 3){
|
|
printf("\n%s\n",rpsraw_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
offset = GetUInt(&(argv[1]),0);
|
|
len = GetUInt(&(argv[2]),0);
|
|
LoadPSHeader(buf,PS_READ_RAW,len,offset);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf);
|
|
if(buf[6] != 0){
|
|
printf("\n read PS raw failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = read(dd,&buf,HCI_MAX_EVENT_SIZE);
|
|
if(iRet < 0){
|
|
printf("\n read PS raw failed\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nOffset :%X\nLength:%X\nData:\n",offset,len);
|
|
|
|
for(i=4,j=1;i<iRet;i++,j++){
|
|
printf("%02X ",buf[i]);
|
|
if(j%16 == 0)
|
|
printf("\n");
|
|
}
|
|
printf("\n\n");
|
|
hci_close_dev(dd);
|
|
}
|
|
static const char *wpsraw_help =
|
|
"Usage:\n"
|
|
"\n wpsraw <offset> <length> <data>\n"
|
|
"\n Example:\n"
|
|
"\n wpsraw 0x012C 6 00 03 F4 55 AB 77 \n";
|
|
|
|
static void cmd_wpsraw(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int offset,len,i;
|
|
if(argc < 4){
|
|
printf("\n%s\n",wpsraw_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
offset = GetUInt(&(argv[1]),0);
|
|
len = GetUInt(&(argv[2]),0);
|
|
if(argc < len+3){
|
|
printf("\nData is less than Length\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
LoadPSHeader(buf,PS_WRITE_RAW,len,offset);
|
|
for(i=0;i<len;i++){
|
|
buf[i+4] = strtol(argv[i+3], NULL, 16);
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER + len, buf);
|
|
if(buf[6] != 0){
|
|
printf("\n Write PS tag failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *peek_help =
|
|
"\nUsage:"
|
|
"\npeek <address> <width>\n"
|
|
"\nExample:\n"
|
|
"\npeek 0x00004FFC 5\n";
|
|
static void cmd_peek(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int address,width,value;
|
|
if(argc < 2){
|
|
printf("\n%s\n",peek_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
address = GetUInt(&(argv[1]),0);
|
|
if(argc == 3)
|
|
width = GetUInt(&(argv[2]),0x4);
|
|
else
|
|
width = 4;
|
|
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = (UCHAR)width; //Memory width
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
value = buf[10];
|
|
value = ((value << 8) | buf[9]);
|
|
value = ((value << 8) | buf[8]);
|
|
value = ((value << 8) | buf[7]);
|
|
|
|
printf("\n0x%X : 0x%X \n",address,value);
|
|
//printf("\n0x%X : 0x%02X%02X%02X%02X \n",address,buf[7],buf[8],buf[9],buf[10]);
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *cwtx_help =
|
|
"\nUsage:"
|
|
"\ncwtx <channel number>\n"
|
|
"\nExample:\n"
|
|
"\ncwtx 40"
|
|
"\n\n";
|
|
|
|
static void cmd_cwtx(int dev_id, int argc, char **argv){
|
|
int dd,iRet, Length = 0;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
char channel;
|
|
if(argc != 2){
|
|
printf("\n%s\n",cwtx_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
channel = atoi(argv[1]);
|
|
if(channel > 78 || channel < 0){
|
|
printf("\nPlease enter channel 0-78!\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,Length,buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x80;
|
|
buf[1] = 0x20;
|
|
buf[2] = 0x02;
|
|
buf[3] = 0x00;
|
|
buf[4] = 0x04;
|
|
buf[5] = 0xFF;
|
|
buf[6] = 0x08;
|
|
buf[7] = 0xC0;
|
|
buf[8] = 0x00;
|
|
buf[9] = 0xFF;
|
|
buf[10] = 0xFF;
|
|
buf[11] = 0xFF;
|
|
buf[12] = 0xFF;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
/* hcitool cmd 0x3F 0x06 0x34 0x20 0x02 0x00 0x04 0x88 0xA0 0x00 0x02 0xFF 0xFF 0xFF 0xFF */
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x34;
|
|
buf[1] = 0x20;
|
|
buf[2] = 0x02;
|
|
buf[3] = 0x00;
|
|
buf[4] = 0x04;
|
|
buf[5] = 0x88;
|
|
buf[6] = 0xA0;
|
|
buf[7] = 0x00;
|
|
buf[8] = 0x02;
|
|
buf[9] = 0xFF;
|
|
buf[10] = 0xFF;
|
|
buf[11] = 0xFF;
|
|
buf[12] = 0xFF;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
/* hcitool cmd 0x3F 0x06 0x28 0x20 0x02 0x00 0x04 0x00 0x90 0x05 0x20 0xFF 0xFF 0xFF 0xFF */
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x28;
|
|
buf[1] = 0x20;
|
|
buf[2] = 0x02;
|
|
buf[3] = 0x00;
|
|
buf[4] = 0x04;
|
|
buf[5] = 0x00;
|
|
buf[6] = 0x90;
|
|
buf[7] = 0x05;
|
|
buf[8] = 0x20;
|
|
buf[9] = 0xFF;
|
|
buf[10] = 0xFF;
|
|
buf[11] = 0xFF;
|
|
buf[12] = 0xFF;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
/* hcitool cmd 0x3F 0x06 0x7C 0x08 0x02 0x00 0x04 0x01 0x00 0x00 0x4B 0xFF 0xFF 0xFF 0xFF */
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x7C;
|
|
buf[1] = 0x08;
|
|
buf[2] = 0x02;
|
|
buf[3] = 0x00;
|
|
buf[4] = 0x04;
|
|
buf[5] = 0x01;
|
|
buf[6] = 0x00;
|
|
buf[7] = 0x00;
|
|
buf[8] = 0x4B;
|
|
buf[9] = 0xFF;
|
|
buf[10] = 0xFF;
|
|
buf[11] = 0xFF;
|
|
buf[12] = 0xFF;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
|
|
/* hcitool cmd 0x3F 0x06 0x00 0x08 0x02 0x00 0x04 $number 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF */
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x00;
|
|
buf[1] = 0x08;
|
|
buf[2] = 0x02;
|
|
buf[3] = 0x00;
|
|
buf[4] = 0x04;
|
|
buf[5] = channel; /* Num */
|
|
buf[6] = 0x00;
|
|
buf[7] = 0x00;
|
|
buf[8] = 0x00;
|
|
buf[9] = 0xFF;
|
|
buf[10] = 0xFF;
|
|
buf[11] = 0xFF;
|
|
buf[12] = 0xFF;
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nEntering continuous wave Tx on channel %d\n",channel);
|
|
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
|
|
static const char *poke_help =
|
|
"\nUsage:"
|
|
"\npoke <address> <value> <mask> <width>\n"
|
|
"\nExample:\n"
|
|
"\npoke 0x580000 0x22005FF 0xFFFFFFFF 4"
|
|
"\n\n";
|
|
|
|
static void cmd_poke(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
int address,width,value,mask;
|
|
if(argc < 2){
|
|
printf("\n%s\n",poke_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
address = GetUInt(&(argv[1]),0);
|
|
value = GetUInt(&(argv[2]),0);
|
|
printf("\nARGC :%d\n",argc);
|
|
if(argc < 4)
|
|
mask = 0xffffffff;
|
|
else
|
|
mask = GetUInt(&(argv[3]),0xFFFFFFFF);
|
|
if(argc < 5)
|
|
width = 4;
|
|
else
|
|
width = GetUInt(&(argv[4]),0x4);
|
|
buf[0] = (address & 0xFF);
|
|
buf[1] = ((address >>8) & 0xFF);
|
|
buf[2] = ((address>>16) & 0xFF);
|
|
buf[3] = ((address>>24) & 0xFF);
|
|
buf[4] = width; //Memory width
|
|
buf[5] = (value & 0xFF);
|
|
buf[6] = ((value >> 8) & 0xFF);
|
|
buf[7] = ((value >> 16) & 0xFF);
|
|
buf[8] = ((value >> 24) & 0xFF);
|
|
buf[9] = (mask & 0xFF);
|
|
buf[10] = ((mask >>8) & 0xFF);
|
|
buf[11] = ((mask>>16) & 0xFF);
|
|
buf[12] = ((mask>>24) & 0xFF);
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nPoke successful!\n");
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
|
|
|
|
static const char *dump_help =
|
|
"\nUsage:"
|
|
"\ndump audio - Display Audio statistics\n"
|
|
"\ndump dma- Display DMA statistics\n"
|
|
"\ndump dma r - Display and Reset DMA statistics\n"
|
|
"\ndump tpc - Dump TPC tables\n"
|
|
"\nExample:\n"
|
|
"\ndump audio"
|
|
"\ndump dma"
|
|
"\ndump dma r"
|
|
"\ndump tpc"
|
|
"\n";
|
|
|
|
|
|
static void cmd_dump(int dev_id, int argc, char **argv){
|
|
int dd;
|
|
if(argc < 2){
|
|
printf("\n%s\n",dump_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
if(!strncmp(argv[1],"audio",5)){
|
|
ReadAudioStats(dd);
|
|
}
|
|
else if(!strncmp(argv[1],"dma",3)){
|
|
ReadGlobalDMAStats(dd);
|
|
if(argc == 3 && !strncmp(argv[2],"r",1)){
|
|
ResetGlobalDMAStats(dd);
|
|
}
|
|
}
|
|
else if(!strncmp(argv[1],"tpc",3)){
|
|
ReadTpcTable(dd);
|
|
}
|
|
else{
|
|
printf("\nInvalid option");
|
|
printf("\n%s\n",dump_help);
|
|
}
|
|
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
static const char *rafh_help =
|
|
"\nUsage:"
|
|
"\nrafh <connection handle>\n"
|
|
"\nExample:\n"
|
|
"\nrafh 0x15"
|
|
"\n\n";
|
|
|
|
static void cmd_rafh(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
short int handle;
|
|
|
|
if(argc < 2){
|
|
printf("\n%s\n",rafh_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
handle = GetUInt(&(argv[1]),0);
|
|
buf[0] = (handle & 0xFF);
|
|
buf[1] = ((handle >>8) & 0xFF);
|
|
iRet = writeHciCommand(dd, OGF_STATUS_PARAM,OCF_READ_AFH_MAP, 2, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nRead AFH failed due to reason :0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
|
|
if(buf[9] == 0)
|
|
printf(" AFH is disabled");
|
|
else
|
|
printf(" AFH is enabled");
|
|
|
|
handle = (buf[7] | (buf[8] << 8));
|
|
printf("\n AFH chaneel classification for handle: 0x%X",handle);
|
|
int i;
|
|
printf("\n Channel Classification Map :");
|
|
for(i=iRet-1; i>9 ; i--){
|
|
printf("%X",buf[i]);
|
|
}
|
|
printf("\n");
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *safh_help =
|
|
"\nUsage:"
|
|
"\nsafh <host channel classification>\n"
|
|
"\nExample:\n"
|
|
"\nsafh 0x7FFFFFFFFFFFFFFFFFFF"
|
|
"\n\n";
|
|
|
|
static void cmd_safh(int dev_id, int argc, char **argv){
|
|
int dd,iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if(argc < 2){
|
|
printf("\n%s\n",safh_help);
|
|
return;
|
|
}
|
|
int i,j;
|
|
i = strlen(argv[1]);
|
|
if(i > 20 || i < 20){
|
|
printf("\n%s\n",safh_help);
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(&buf,0,HCI_MAX_EVENT_SIZE);
|
|
const char *map = argv[1];
|
|
char byte[3];
|
|
int data;
|
|
for (i = 0,j=9; i < 20 ; i+=2,j--) {
|
|
memcpy(byte,&map[i],2);
|
|
byte[2] = '\0';
|
|
data = strtol(byte, NULL, 16);
|
|
buf[j] = (data & 0xFF);
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_SET_AFH_CLASSIFICATION,10, buf);
|
|
if(buf[6] != 0){
|
|
printf("\nSet AFH failed due to reason :0x%X\n",buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nSet AFH successful!\n");
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *wotp_help =
|
|
"\nUsage:"
|
|
"\nwotp <address> <data> [length=1]\n"
|
|
"\nExample:\n"
|
|
"\nwotp 0x15 0x2020 2"
|
|
"\n\n";
|
|
|
|
static void cmd_wotp(int dev_id, int argc, char **argv)
|
|
{
|
|
int address, length;
|
|
|
|
if (argc < 3) {
|
|
printf("\n%s\n", wotp_help);
|
|
return;
|
|
}
|
|
if (argc == 4)
|
|
length = GetUInt(&argv[3], 1);
|
|
else
|
|
length = 1;
|
|
address = GetUInt(&argv[1], 0xffffffff);
|
|
if (address == 0xffffffff) {
|
|
printf("\n%s\n", wotp_help);
|
|
return;
|
|
}
|
|
ReverseHexString(argv[2]);
|
|
if (!write_otpRaw(dev_id, address, length, (UCHAR *)argv[2]))
|
|
printf("Write to OTP successful!\n");
|
|
}
|
|
|
|
static int write_otpRaw(int dev_id, int address, int length, UCHAR *data)
|
|
{
|
|
int dd, iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return dd;
|
|
}
|
|
memset(&buf, 0, HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x12; /* write RAW OTP */
|
|
buf[1] = address & 0xFF; /* PS tag */
|
|
buf[2] = (address >> 8) & 0xFF;
|
|
buf[3] = length; /* Entry Size */
|
|
GetByteSeq(buf + 4, data, 244); /* Entry Data */
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, 244 + PS_COMMAND_HEADER, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nWrite to OTP failed due to reason :0x%X\n", buf[6]);
|
|
hci_close_dev(dd);
|
|
return buf[6];
|
|
}
|
|
hci_close_dev(dd);
|
|
return 0;
|
|
}
|
|
|
|
static const char *rotp_help =
|
|
"\nUsage:"
|
|
"\nrotp <address> [length=1]\n"
|
|
"\nExample:\n"
|
|
"\nrotp 0x15 2"
|
|
"\n\n";
|
|
|
|
static void cmd_rotp(int dev_id, int argc, char **argv)
|
|
{
|
|
int address, length;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if (argc < 2) {
|
|
printf("\n%s\n", rotp_help);
|
|
return;
|
|
}
|
|
if (argc == 3)
|
|
length = GetUInt(&argv[2], 1);
|
|
else
|
|
length = 1;
|
|
address = GetUInt(&argv[1], 0xffffffff);
|
|
if (address == 0xffffffff) {
|
|
printf("\n%s\n", rotp_help);
|
|
return;
|
|
}
|
|
if (!read_otpRaw(dev_id, address, length, buf))
|
|
dumpHex(buf, length, 8);
|
|
}
|
|
|
|
static int read_otpRaw(int dev_id, int address, int length, UCHAR *data)
|
|
{
|
|
int dd, iRet, plen;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return dd;
|
|
}
|
|
memset(&buf, 0, HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x11; /* read OTP */
|
|
buf[1] = address & 0xFF; /* PS tag */
|
|
buf[2] = (address >> 8) & 0xFF;
|
|
buf[3] = length; /* Entry Size */
|
|
buf[4] = 0x00; /* Entry Data */
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, 244 + PS_COMMAND_HEADER, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nRead from OTP failed due to reason :0x%X\n", buf[6]);
|
|
hci_close_dev(dd);
|
|
return buf[6];
|
|
}
|
|
do {
|
|
plen = read(dd, buf, HCI_MAX_EVENT_SIZE);
|
|
if (plen < 0) {
|
|
perror("Read OTP error\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_PS);
|
|
memcpy(data, buf + HCI_EVENT_HEADER_SIZE + 1, length);
|
|
hci_close_dev(dd);
|
|
return 0;
|
|
}
|
|
|
|
static int SU_GetId(int dev_id, char *pStr, tSU_RevInfo *pRetRevInfo)
|
|
{
|
|
tSU_RevInfo RevInfo;
|
|
int dd, iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
RevInfo.RomVersion = 0x99999999;
|
|
RevInfo.BuildVersion = 0x99999999;
|
|
RevInfo.RadioFormat = 0xffff;
|
|
RevInfo.SysCfgFormat = 0xffff;
|
|
|
|
memset(buf, 0, HCI_MAX_EVENT_SIZE);
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return dd;
|
|
}
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_VERSION, 0, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nRead version failed due to reason :0x%X\n", buf[6]);
|
|
return buf[6];
|
|
}
|
|
RevInfo.RomVersion = buf[7] + (buf[8]<<8) + (buf[9]<<16) + (buf[10]<<24);
|
|
RevInfo.BuildVersion = buf[11] + (buf[12]<<8) + (buf[13]<<16) + (buf[14]<<24);
|
|
return 0;
|
|
}
|
|
|
|
/*static const char *otp_help =
|
|
"\nUsage:"
|
|
"\notp [dump|imp|exp|test|rpid|wpid|rvid|wvid|rba|wba|hid|cpw|cpw|pwridx|ledo] [file]\n"
|
|
"\notp wba <BdAddr>:\n"
|
|
"\n\n";
|
|
*/
|
|
|
|
static void cmd_otp(int dev_id, int argc, char **argv)
|
|
{
|
|
UCHAR buf[512], format[16];
|
|
FILE *pF = NULL;
|
|
UINT32 data;
|
|
int i;
|
|
|
|
if (argc == 1 || !strcmp(argv[1], "dump")) {
|
|
printf("dump:\n");
|
|
for (i = 0; i < 4; i++) {
|
|
if (read_otpRaw(dev_id, 128 * i, 128, &buf[128*i])) {
|
|
printf("read failed\n");
|
|
return;
|
|
}
|
|
}
|
|
dumpHex(buf, 512, 8);
|
|
} else if (!strcmp(argv[1], "test")) {
|
|
printf("test:\n");
|
|
printf("To be continue.\n");
|
|
} else if (!strcmp(argv[1], "imp")) {
|
|
if (argc < 3 || !*argv[2]) {
|
|
printf("Import file content into OTP. File name is required\n");
|
|
return;
|
|
}
|
|
printf("Import from %s into OTP:\n", argv[2]);
|
|
if (!(pF = fopen(argv[2], "rb"))) {
|
|
printf("Open file failed\n");
|
|
return;
|
|
}
|
|
fread(&buf[0], sizeof(buf), 1, pF);
|
|
fclose(pF);
|
|
for (i = 0; i < 512; i += 4) {
|
|
data = buf[i];
|
|
data <<= 8;
|
|
data += buf[i+1];
|
|
data <<= 8;
|
|
data += buf[i+2];
|
|
data <<= 8;
|
|
data += buf[i+3];
|
|
sprintf((char *)&format, "0x%08x", data);
|
|
if (write_otpRaw(dev_id, i, 4, (UCHAR *)format)) {
|
|
printf("Failed!(%d)\n", i);
|
|
return;
|
|
}
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "exp")) {
|
|
for (i = 0; i < 4; i++) {
|
|
if (read_otpRaw(dev_id, 128 * i, 128, &buf[128*i])) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
}
|
|
if (argc < 3 || !*argv[2] || (!(pF = fopen(argv[2], "wb")))) {
|
|
/* export the content to the screen */
|
|
dumpHex(buf, 512, 8);
|
|
} else {
|
|
/* export the content to the file */
|
|
fwrite(&buf[0], sizeof(buf), 1, pF);
|
|
fclose(pF);
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "ledo")) {
|
|
int opendrain;
|
|
tSU_RevInfo RevInfo;
|
|
|
|
if (SU_GetId(dev_id, NULL, &RevInfo))
|
|
return;
|
|
|
|
printf("RomVer:%02X.%02X.%02X.%02X \n", (UINT8)((RevInfo.RomVersion >> (8*3)) & 0xff),
|
|
(UINT8)((RevInfo.RomVersion >> (8*2)) & 0xff),
|
|
(UINT8)((RevInfo.RomVersion >> 8) & 0xff),
|
|
(UINT8)(RevInfo.RomVersion & 0xff));
|
|
if (((UINT8)((RevInfo.RomVersion >> (8*3)) & 0xff) == 0x01) &&
|
|
((UINT8)((RevInfo.RomVersion >> (8*2)) & 0xff) == 0x02) &&
|
|
((UINT8)((RevInfo.RomVersion >> 8) & 0xff) == 0x02) &&
|
|
((UINT8)(RevInfo.RomVersion & 0xff) == 0x00)) {
|
|
UINT8 LedValue[] = {0xCE, 0xDA, 0x04, 0x0C, 0x58,
|
|
0x04, 0x05, 0x06, 0xff, 0x50,
|
|
0x40, 0x01, 0x24, 0x08, 0x00,
|
|
0x00};
|
|
for (opendrain = 112; opendrain < 128; opendrain++) {
|
|
if (write_otpRaw(dev_id, opendrain, 1, &LedValue[opendrain-112])) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
}
|
|
printf("OTP led opendrain done\n");
|
|
} else {
|
|
printf("Wrong RomVer\n");
|
|
}
|
|
} else if (!strcmp(argv[1], "cpw")) {
|
|
UINT32 cin_value = 0, cout_value = 0;
|
|
char tempStr[8];
|
|
|
|
if (argc < 3) {
|
|
printf("\n Enter cin_value : ");
|
|
scanf("%d", &cin_value);
|
|
} else
|
|
cin_value = GetUInt(&argv[2], 0);
|
|
if (cin_value < 0 || cin_value > 128) {
|
|
printf("Invalid cin_value = %d\n", cin_value);
|
|
return;
|
|
}
|
|
if (argc < 4) {
|
|
printf("\n Enter cout_value : ");
|
|
scanf("%d", &cout_value);
|
|
} else
|
|
cout_value = GetUInt(&argv[3], 0);
|
|
if (cout_value < 0 || cout_value > 128) {
|
|
printf("Invalid cout_value = %d\n", cout_value);
|
|
return;
|
|
}
|
|
if (cout_value & 0x01) cin_value += 0x80;
|
|
sprintf(tempStr, "0x%02x", cin_value);
|
|
if (write_otpRaw(dev_id, 4, 1, (UCHAR *)tempStr)) {
|
|
printf("CapTune Error\n");
|
|
return;
|
|
}
|
|
sprintf(tempStr, "0x%02x", cout_value >> 1);
|
|
if (write_otpRaw(dev_id, 5, 1, (UCHAR *)tempStr)) {
|
|
printf("CapTune Error\n");
|
|
return;
|
|
}
|
|
sprintf(tempStr, "0x40");
|
|
if (write_otpRaw(dev_id, 5, 1, (UCHAR *)tempStr)) {
|
|
printf("CapTune Error\n");
|
|
return;
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "pwridx")) {
|
|
char tempStr[8];
|
|
sprintf(tempStr, "0x02");
|
|
if (write_otpRaw(dev_id, 21, 1, (UCHAR *)tempStr)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "hid")) {
|
|
char tempStr[8];
|
|
UINT32 value = 0;
|
|
if (argc < 3 || !*argv[2]) {
|
|
printf("\n Enter HID value(0|1) : ");
|
|
scanf("%d", &value);
|
|
} else
|
|
value = GetUInt(&argv[2], 0);
|
|
if (value != 0 && value != 1) {
|
|
printf("\n Error: Syntax \"otp hid 0x00|0x01\"\n");
|
|
return;
|
|
}
|
|
sprintf(tempStr, "0x%02x", value);
|
|
if (write_otpRaw(dev_id, 12, 1, (UCHAR *)tempStr)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "wpid")) {
|
|
UINT32 offset = 134;
|
|
size_t len = 0;
|
|
char pid[8] = {0};
|
|
char *ofs = NULL;
|
|
printf("\n Enter OTP_PID_OFFSET(default 134) : ");
|
|
getline(&ofs, &len, stdin);
|
|
sscanf(ofs, "%d", &offset);
|
|
if (ofs) free(ofs);
|
|
memset(pid, 0, sizeof(pid));
|
|
if (argc < 3 || !*argv[2]) {
|
|
printf("\n Enter PID : ");
|
|
fgets((char *)pid, 7, stdin);
|
|
} else
|
|
strncpy((char *)pid, argv[2], 7);
|
|
len = strlen(pid) - 1;
|
|
if (pid[len] == '\n' || pid[len] == '\r')
|
|
pid[len] = 0;
|
|
ReverseHexString(pid);
|
|
if (write_otpRaw(dev_id, offset, 4, (UCHAR *)pid)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "rpid")) {
|
|
UINT32 offset = 134;
|
|
size_t len = 0;
|
|
UCHAR Data[2];
|
|
char *ofs = NULL;
|
|
printf("\n Enter OTP_PID_OFFSET(default 134) : ");
|
|
getline(&ofs, &len, stdin);
|
|
sscanf(ofs, "%d", &offset);
|
|
if (ofs) free(ofs);
|
|
if (read_otpRaw(dev_id, offset, 2, Data)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("The OTP PID is 0x%02x%02x\n", Data[1], Data[0]);
|
|
} else if (!strcmp(argv[1], "wvid")) {
|
|
UINT32 offset = 136;
|
|
size_t len = 0;
|
|
char vid[8] = {0};
|
|
char *ofs = NULL;
|
|
printf("\n Enter OTP_VID_OFFSET(default 136) : ");
|
|
getline(&ofs, &len, stdin);
|
|
sscanf(ofs, "%d", &offset);
|
|
if (ofs) free(ofs);
|
|
memset(vid, 0, sizeof(vid));
|
|
if (argc < 3 || !*argv[2]) {
|
|
printf("\n Enter VID : ");
|
|
fgets(vid, 8, stdin);
|
|
} else
|
|
strncpy(vid, argv[2], 7);
|
|
len = strlen(vid) - 1;
|
|
if (vid[len] == '\n' || vid[len] == '\r')
|
|
vid[len] = 0;
|
|
ReverseHexString(vid);
|
|
if (write_otpRaw(dev_id, offset, 2, (UCHAR *)vid)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "rvid")) {
|
|
UINT32 offset = 136;
|
|
size_t len = 0;
|
|
char *ofs = NULL;
|
|
UCHAR Data[2];
|
|
printf("\n Enter OTP_VID_OFFSET(default 136) : ");
|
|
getline(&ofs, &len, stdin);
|
|
sscanf(ofs, "%d", &offset);
|
|
if (ofs) free(ofs);
|
|
if (read_otpRaw(dev_id, offset, 2, Data)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("The OTP VID is 0x%02x%02x\n", Data[1], Data[0]);
|
|
} else if (!strcmp(argv[1], "wba")) {
|
|
UINT32 offset = 128;
|
|
size_t len = 0;
|
|
char bdaddr[16] = {0};
|
|
char *ofs = NULL;
|
|
printf("\n Enter OTP_BDA_OFFSET(default 128) : ");
|
|
getline(&ofs, &len, stdin);
|
|
sscanf(ofs, "%d", &offset);
|
|
if (ofs) free(ofs);
|
|
memset(bdaddr, 0, sizeof(bdaddr));
|
|
if (argc < 3 || !*argv[2]) {
|
|
printf("\n Enter BDADDR : ");
|
|
fgets(bdaddr, 16, stdin);
|
|
} else
|
|
strncpy(bdaddr, argv[2], 15);
|
|
len = strlen(bdaddr) - 1;
|
|
if (bdaddr[len] == '\n' || bdaddr[len] == '\r')
|
|
bdaddr[len] = 0;
|
|
ReverseHexString(bdaddr);
|
|
if (write_otpRaw(dev_id, offset, 6, (UCHAR *)bdaddr)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("Done\n");
|
|
} else if (!strcmp(argv[1], "rba")) {
|
|
UINT32 offset = 128;
|
|
size_t len = 0;
|
|
char *ofs = NULL;
|
|
UCHAR Data[6];
|
|
printf("\n Enter OTP_BDA_OFFSET(default 128) : ");
|
|
getline(&ofs, &len, stdin);
|
|
sscanf(ofs, "%d", &offset);
|
|
if (ofs) free(ofs);
|
|
if (read_otpRaw(dev_id, offset, 6, Data)) {
|
|
printf("Failed\n");
|
|
return;
|
|
}
|
|
printf("The OTP BDADDR is 0x%02x%02x%02x%02x%02x%02x\n",
|
|
Data[5], Data[4], Data[3], Data[2], Data[1], Data[0]);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
static const char *plb_help =
|
|
"\nUsage:"
|
|
"\nplb [1|0]\n"
|
|
"\nplb 1\n"
|
|
"\n\n";
|
|
#endif
|
|
|
|
static void cmd_plb(int dev_id, int argc, char **argv)
|
|
{
|
|
int dd, enable, iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
if (argc < 2)
|
|
enable = 1;
|
|
else
|
|
enable = GetUInt(&argv[1], 1);
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(buf, 0, HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x09; /* audio commmand opcode */
|
|
buf[4] = (enable == 0) ? 0x00 : 0x01; /* audio command param */
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_AUDIO_CMD, 8, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nError in setting PCM CODEC loopback :0x%X\n", buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("\nPCM CODEC loopback is %s\n", (enable == 0) ? "OFF" : "ON");
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
#if 0
|
|
static const char *psw_help =
|
|
"\nUsage:"
|
|
"\npsw [1|0] [Frequency]\n"
|
|
"\npsw 1 3000\n"
|
|
"\n\n";
|
|
#endif
|
|
|
|
static void cmd_psw(int dev_id, int argc, char **argv)
|
|
{
|
|
int dd, enable, freq, iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
if (argc < 2) {
|
|
enable = 1;
|
|
freq = 440;
|
|
}
|
|
else if (argc < 3) {
|
|
printf("aa\n");
|
|
enable = GetUInt(&argv[1], 1);
|
|
freq = 440;
|
|
} else {
|
|
enable = GetUInt(&argv[1], 1);
|
|
freq = GetUInt(&argv[2], 440);
|
|
}
|
|
if (freq > 3700) {
|
|
printf("Invalid frequency. It should be in the range of 0 to 3700\n");
|
|
return;
|
|
}
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
memset(buf, 0, HCI_MAX_EVENT_SIZE);
|
|
buf[0] = 0x0a; /* audio command opcode */
|
|
buf[4] = (enable == 0) ? 0x00 : 0x01; /* audio command param */
|
|
buf[5] = 0x00;
|
|
buf[6] = freq & 0xff;
|
|
buf[7] = (freq >> 8) & 0xff;
|
|
|
|
iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_AUDIO_CMD, 8, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nError in running PCM sine wave playback :0x%X\n", buf[6]);
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("PCM CODEC PCM sine wave playback is %s\n", (enable == 0) ? "OFF" : "ON");
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *lert_help=
|
|
"\nUsage:"
|
|
"\nlert <rx_channel>\n"
|
|
"\nlert 30 \n"
|
|
"\n\n";
|
|
|
|
static void cmd_lert(int dev_id, int argc, char **argv)
|
|
{
|
|
int dd;
|
|
UCHAR channel;
|
|
if (argc < 2) {
|
|
printf("\n%s\n", lert_help);
|
|
return;
|
|
}
|
|
channel = (UCHAR)GetUInt(&argv[1], 0);
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
|
|
SU_LERxTest(dd, channel);
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static BOOL SU_LERxTest(int dd, UCHAR channel)
|
|
{
|
|
int iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if (channel < MB_MIN_FREQUENCY_LE || channel > MB_MAX_FREQUENCY_LE) {
|
|
printf("Invalid rx channel. It should be in the range of %d to %d\n",
|
|
MB_MIN_FREQUENCY_LE, MB_MAX_FREQUENCY_LE);
|
|
return FALSE;
|
|
}
|
|
|
|
memset(buf, 0, HCI_MAX_EVENT_SIZE);
|
|
buf[0] = channel; /* rx_channel */
|
|
iRet = writeHciCommand(dd, OGF_LE_CTL, OCF_LE_RECEIVER_TEST, 1, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nError in putting the device into LE RX mode\n");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static const char *lett_help=
|
|
"\nUsage:"
|
|
"\nlett <rx_channel> <length> <packet_payload>\n"
|
|
"\nlett 30 30 5\n"
|
|
"\n\n";
|
|
|
|
static void cmd_lett(int dev_id, int argc, char **argv)
|
|
{
|
|
int dd;
|
|
UCHAR channel, length, payload;
|
|
if (argc < 4) {
|
|
printf("\n%s\n", lett_help);
|
|
return;
|
|
}
|
|
channel = (UCHAR)GetUInt(&argv[1], 0);
|
|
length = (UCHAR)GetUInt(&argv[2], 0);
|
|
payload = (UCHAR)GetUInt(&argv[3], 0);
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
SU_LETxTest(dd, channel, length, payload);
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static BOOL SU_LETxTest(int dd, UCHAR channel, UCHAR length, UCHAR payload)
|
|
{
|
|
int iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if (channel < MB_MIN_FREQUENCY_LE || channel > MB_MAX_FREQUENCY_LE) {
|
|
printf("Invalid tx channel. It should be in the range of %d to %d\n",
|
|
MB_MIN_FREQUENCY_LE, MB_MAX_FREQUENCY_LE);
|
|
return FALSE;
|
|
}
|
|
if (length < MB_MIN_DATALEN_LE || length > MB_MAX_DATALEN_LE) {
|
|
printf("Invalid data length. It should be in the range of %d to %d\n",
|
|
MB_MIN_DATALEN_LE, MB_MAX_DATALEN_LE);
|
|
return FALSE;
|
|
}
|
|
if (payload > 7) {
|
|
printf("Invalid packet payload. It should be in the range of 0 to 7\n");
|
|
return FALSE;
|
|
}
|
|
|
|
memset(buf, 0, HCI_MAX_EVENT_SIZE);
|
|
buf[0] = channel; /* tx_channel */
|
|
buf[1] = length; /* length of test data */
|
|
buf[2] = payload; /* packet payload */
|
|
iRet = writeHciCommand(dd, OGF_LE_CTL, OCF_LE_TRANSMITTER_TEST, 3, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nError in putting the device into LE TX mode\n");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#if 0
|
|
static const char *lete_help =
|
|
"\nUsage:"
|
|
"\nlete\n"
|
|
"\n\n";
|
|
#endif
|
|
|
|
static void cmd_lete(int dev_id, int argc, char **argv)
|
|
{
|
|
int dd, iRet;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
memset(buf, 0, HCI_MAX_EVENT_SIZE);
|
|
iRet = writeHciCommand(dd, OGF_LE_CTL, OCF_LE_TEST_END, 0, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nError in ending LE test\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
printf("Number of packets = %d\n", buf[7] | (buf[8] << 8));
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static const char *tputs_help =
|
|
"\nUsage:"
|
|
"\ntput-s [BD_Addr] [Judgment value] Logfile times"
|
|
"\ntput-s 11:22:33:44:55:66 150 log.txt 10"
|
|
"\n\n";
|
|
|
|
static void CalculateTput(int dd, UINT16 hci_handle, char *filename, double threshold, int tx_size)
|
|
{
|
|
time_t start, finish, checkbreak;
|
|
UCHAR buf[1009];
|
|
FILE *fp = NULL;
|
|
int aclnum = 8;
|
|
int retval;
|
|
unsigned long sentnum = 0;
|
|
double TimeResult = 0;
|
|
fd_set rfds;
|
|
struct hci_filter flt;
|
|
struct timeval tv1, tv2, timeout;
|
|
unsigned long long start_utime, end_utime, time_diff;
|
|
unsigned long long throughput;
|
|
|
|
hci_filter_clear(&flt);
|
|
hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
|
|
hci_filter_set_event(EVT_NUM_COMP_PKTS, &flt);
|
|
if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
|
|
perror("HCI filter setup failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
start = time(NULL);
|
|
gettimeofday(&tv1, NULL);
|
|
start_utime = tv1.tv_sec*1000000 + tv1.tv_usec;
|
|
while (sentnum < 1024 * tx_size) {
|
|
while (aclnum > 0) {
|
|
aclnum--;
|
|
buf[0] = HCI_ACLDATA_PKT;
|
|
/* ACL packet header */
|
|
buf[1] = hci_handle & 0xFF;
|
|
buf[2] = ((hci_handle >> 8) & 0x0E);
|
|
buf[3] = 1004 & 0xff;
|
|
buf[4] = (1004 >> 8) & 0xff;
|
|
/* L2CAP packet header */
|
|
buf[5] = 1000 & 0xff;
|
|
buf[6] = (1000 >> 8) & 0xff;
|
|
buf[7] = 0x40 & 0xff;
|
|
buf[8] = 0;
|
|
|
|
memset(buf+9, sentnum++, 1000);
|
|
while (write(dd, (const void *)buf, 1009) < 0) {
|
|
if (errno == EAGAIN || errno == EINTR)
|
|
continue;
|
|
perror("HCI send packet failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
timeout.tv_sec = 5;
|
|
timeout.tv_usec = 0;
|
|
|
|
FD_ZERO(&rfds);
|
|
FD_SET(dd, &rfds);
|
|
retval = select(dd+1, &rfds, NULL, NULL, &timeout);
|
|
if (retval == -1) {
|
|
perror("select()");
|
|
exit(EXIT_FAILURE);
|
|
} else if (retval) {
|
|
/* Data is available now */
|
|
ssize_t plen;
|
|
UCHAR buffer[64];
|
|
int i;
|
|
plen = read(dd, buffer, 64);
|
|
if (plen < 0) {
|
|
perror("HCI read buffer failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
for (i = 0; i < buffer[HCI_EVENT_HEADER_SIZE]; i++)
|
|
aclnum += (buffer[HCI_EVENT_HEADER_SIZE+(i+1)*2+1] | (buffer[HCI_EVENT_HEADER_SIZE+(i+1)*2+2] << 8));
|
|
}
|
|
checkbreak = time(NULL);
|
|
if ((checkbreak - start) >= 300) break;
|
|
}
|
|
finish = time(NULL);
|
|
gettimeofday(&tv2, NULL);
|
|
end_utime = tv2.tv_sec*1000000 + tv2.tv_usec;
|
|
time_diff = end_utime - start_utime;
|
|
throughput = time_diff/1000;
|
|
throughput = (sentnum * 1000)/throughput;
|
|
printf("Transfer Completed! throughput [%0d KB/s]", (int)throughput);
|
|
printf(" result [%s]\n", threshold > throughput ? " Fail " : " Pass ");
|
|
if (filename && *filename)
|
|
fp = fopen(filename, "at+");
|
|
if (fp) {
|
|
fprintf(fp, "Transfer Completed! throughput [%.0f KB/s]", TimeResult);
|
|
fprintf(fp, " result [%s]\n", threshold > TimeResult ? " Fail " : " Pass ");
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
static void cmd_tputs(int dev_id, int argc, char **argv)
|
|
{
|
|
int j, dd, iRet, loop = 1, tx_test_size = 1;
|
|
UINT16 Ps_EntrySize = 0;
|
|
UINT16 hci_handle = 0;
|
|
double threshold = 0.0;
|
|
char *filename = NULL;
|
|
struct sigaction sa;
|
|
FILE *fp = NULL;
|
|
bdaddr_t bdaddr;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
UCHAR Ps_Data[HCI_MAX_EVENT_SIZE];
|
|
UINT16 *pPs_Data;
|
|
BOOL Ok = FALSE;
|
|
char timeString[9] = {0};
|
|
char dateString[15] = {0};
|
|
time_t current_time;
|
|
struct tm *time_info;
|
|
tSU_RevInfo RevInfo;
|
|
|
|
if (argc < 3) {
|
|
printf("\n%s\n", tputs_help);
|
|
return;
|
|
}
|
|
|
|
if (str2ba(argv[1],&bdaddr)) {
|
|
printf("\nPlease input valid bdaddr.\n");
|
|
return;
|
|
}
|
|
threshold = atof(argv[2]);
|
|
if (!threshold) {
|
|
printf("\nPlease input valid throughput threshold.\n");
|
|
return;
|
|
}
|
|
if (argc > 3)
|
|
filename = strdup(argv[3]);
|
|
if (argc > 4)
|
|
loop = GetUInt(&argv[4], 1);
|
|
if (argc > 5)
|
|
tx_test_size = GetUInt(&argv[5],1);
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
CtrlCBreak = FALSE;
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.sa_handler = sig_term;
|
|
sigaction(SIGTERM, &sa, NULL);
|
|
sigaction(SIGINT, &sa, NULL);
|
|
PSInit(dd);
|
|
memset(buf, 0, sizeof(buf));
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_RESET, 0, buf);
|
|
if (buf[6] != 0) {
|
|
printf("Error: HCI RESET failed.\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
sleep(1);
|
|
for (j = 0; j < loop; j++) {
|
|
int i = 0;
|
|
if (!j) sleep(1);
|
|
printf("\n-----------------------------------");
|
|
printf("\nTimes %d/%d\n", j + 1, loop);
|
|
|
|
time(¤t_time);
|
|
time_info = localtime(¤t_time);
|
|
strftime(timeString, sizeof(timeString), "%H %M %S", time_info);
|
|
strftime(dateString, sizeof(dateString), "%b %d %Y", time_info);
|
|
if (j == 0) {
|
|
if (filename && *filename)
|
|
fp = fopen(filename, "at+");
|
|
if (fp != NULL)
|
|
fprintf(fp, "\n[%s %s] \nCMD : TPUT-S %s %f %s %d\n",
|
|
dateString, timeString, argv[1], threshold, filename, loop);
|
|
/* SFLAGS FW */
|
|
Ok = PSOperations(dd, PS_GET_LENGTH, PSTAG_RF_TEST_BLOCK_START, (UINT32 *)&Ps_EntrySize);
|
|
if (Ok) {
|
|
Ps_Data[0] = Ps_EntrySize & 0xff;
|
|
Ps_Data[1] = (Ps_EntrySize >> 8) & 0xff;
|
|
Ok = PSOperations(dd, PS_READ, PSTAG_RF_TEST_BLOCK_START, (UINT32 *)&Ps_Data);
|
|
if (Ok) {
|
|
pPs_Data = (UINT16 *)&Ps_Data[0];
|
|
if (*pPs_Data == BT_SOC_INIT_TOOL_START_MAGIC_WORD) {
|
|
RevInfo.RadioFormat = *(pPs_Data + 1);
|
|
RevInfo.RadioContent = *(pPs_Data + 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Get syscfg info */
|
|
Ok = PSOperations(dd, PS_GET_LENGTH, PSTAG_SYSCFG_PARAM_TABLE0, (UINT32 *)&Ps_EntrySize);
|
|
if (Ok) {
|
|
Ps_Data[0] = Ps_EntrySize & 0xff;
|
|
Ps_Data[1] = (Ps_EntrySize >> 8) & 0xff;
|
|
Ok = PSOperations(dd, PS_READ, PSTAG_SYSCFG_PARAM_TABLE0, (UINT32 *)&Ps_Data);
|
|
if (Ok) {
|
|
pPs_Data = (UINT16 *)&Ps_Data[0];
|
|
if (*pPs_Data == 0xC1C1) {
|
|
RevInfo.SysCfgFormat = *(pPs_Data + 1);
|
|
RevInfo.SysCfgContent = *(pPs_Data + 2);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (RevInfo.SysCfgFormat != 0xff) {
|
|
printf("SysCfg - Format: %d.%d\n",((RevInfo.SysCfgFormat >> 4) & 0xfff), (RevInfo.SysCfgFormat & 0xf));
|
|
printf(" Content: %d\n", RevInfo.SysCfgContent);
|
|
if (fp) {
|
|
fprintf(fp, "SysCfg - Format: %d.%d\n",((RevInfo.SysCfgFormat >> 4) & 0xfff),
|
|
(RevInfo.SysCfgFormat & 0xf));
|
|
fprintf(fp, " Content: %d\n", RevInfo.SysCfgContent);
|
|
}
|
|
} else {
|
|
printf("SysCfg - N/A\n");
|
|
if(fp)
|
|
fprintf(fp, "SysCfg - N/A\n");
|
|
}
|
|
|
|
/* bd addr */
|
|
memset(&buf, 0, sizeof(buf));
|
|
iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf);
|
|
if (buf[6] != 0) {
|
|
printf("\nCould not read the BD_ADDR (time out)\n");
|
|
} else {
|
|
char temp[16] = {0};
|
|
memset(temp, 0, sizeof(temp));
|
|
sprintf(temp, "%02X%02X%02X%02X%02X%02X", buf[iRet-1], buf[iRet-2],
|
|
buf[iRet-3], buf[iRet-4], buf[iRet-5], buf[iRet-6]);
|
|
printf("\nLocal BDAddress : 0x%s\n", temp);
|
|
if (fp)
|
|
fprintf(fp, "Local BDAddress : 0x%s\n", temp);
|
|
}
|
|
|
|
if (fp) {
|
|
fclose(fp);
|
|
fp = NULL;
|
|
}
|
|
}
|
|
printf("Sending packages to 0x%s\n", argv[1]);
|
|
while (i++ < 3) {
|
|
iRet = hci_create_connection(dd, &bdaddr, 0xCC18, 0, 0, &hci_handle, 0);
|
|
if (!iRet || CtrlCBreak) break;
|
|
}
|
|
|
|
if (iRet) {
|
|
if (filename && *filename) {
|
|
fp = fopen(filename, "at+");
|
|
if (fp) {
|
|
fprintf(fp, "Transfer Failed! \n");
|
|
fclose(fp);
|
|
fp = NULL;
|
|
}
|
|
}
|
|
printf("Transfer Failed! \n");
|
|
CtrlCBreak = TRUE;
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
CalculateTput(dd, hci_handle, filename, threshold, tx_test_size);
|
|
|
|
hci_disconnect(dd, hci_handle, 0, 30);
|
|
|
|
if (CtrlCBreak) break;
|
|
}
|
|
CtrlCBreak = TRUE;
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static void cmd_tputr(int dev_id, int argc, char **argv)
|
|
{
|
|
int dd, iRet;
|
|
ssize_t plen;
|
|
UINT16 hci_handle = 0;
|
|
UCHAR buf[HCI_MAX_EVENT_SIZE];
|
|
struct hci_filter flt;
|
|
struct sigaction sa;
|
|
|
|
if (dev_id < 0)
|
|
dev_id = hci_get_route(NULL);
|
|
dd = hci_open_dev(dev_id);
|
|
if (dd < 0) {
|
|
perror("\nERROR: Can not open HCI device\n");
|
|
return;
|
|
}
|
|
CtrlCBreak = FALSE;
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.sa_handler = sig_term;
|
|
sigaction(SIGTERM, &sa, NULL);
|
|
sigaction(SIGINT, &sa, NULL);
|
|
memset(buf, 0, sizeof(buf));
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_RESET, 0, buf);
|
|
if (buf[6] != 0) {
|
|
printf("Error: HCI RESET failed.\n");
|
|
hci_close_dev(dd);
|
|
return;
|
|
}
|
|
sleep(1);
|
|
memset(buf, 0, sizeof(buf));
|
|
buf[0] = 0x02;
|
|
iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf);
|
|
if (buf[6] != 0) {
|
|
printf("Error: Write scan failed\n");
|
|
return;
|
|
}
|
|
hci_filter_clear(&flt);
|
|
hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
|
|
hci_filter_all_events(&flt);
|
|
if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
|
|
perror("HCI filter setup failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf("Start listening ...\n");
|
|
do {
|
|
plen = read(dd, buf, HCI_MAX_EVENT_SIZE);
|
|
if (plen < 0) {
|
|
printf("reading failed...\n");
|
|
if (errno == EAGAIN || errno == EINTR) continue;
|
|
else {
|
|
perror("HCI read failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
if (buf[1] == EVT_CONN_REQUEST) {
|
|
int i, j;
|
|
ssize_t plen = 0;
|
|
printf("Connection come in\n");
|
|
for (i = 0, j = 3; i < BD_ADDR_SIZE; i++, j++)
|
|
buf[i] = buf[j];
|
|
buf[BD_ADDR_SIZE] = 0x01;
|
|
if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ, 7, buf)) {
|
|
printf("Accept connection error\n");
|
|
return;
|
|
}
|
|
do {
|
|
plen = read(dd, buf, HCI_MAX_EVENT_SIZE);
|
|
if (plen < 0) {
|
|
perror("Read failed");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} while (buf[1] != EVT_CONN_COMPLETE);
|
|
if (buf[3] == 0) {
|
|
printf("Connection up\n");
|
|
} else {
|
|
printf("Connection failed\n");
|
|
}
|
|
hci_handle = (buf[4] | (buf[5] << 8)) & 0x0EFF;
|
|
} else if (buf[1] == EVT_DISCONN_COMPLETE) {
|
|
UINT16 hdl = buf[4] | (buf[5] << 8);
|
|
printf("Disconnect...\n");
|
|
if (hdl == hci_handle) {
|
|
break;
|
|
}
|
|
} else if (CtrlCBreak) {
|
|
printf("CtrlBreak...\n");
|
|
break;
|
|
}
|
|
} while (plen >= 0);
|
|
CtrlCBreak = TRUE;
|
|
hci_close_dev(dd);
|
|
}
|
|
|
|
static void sig_term(int sig)
|
|
{
|
|
if (CtrlCBreak) return;
|
|
CtrlCBreak = TRUE;
|
|
}
|
|
|
|
static struct {
|
|
char *cmd;
|
|
char *cmd_option;
|
|
void (*func)(int dev_id, int argc, char **argv);
|
|
char *doc;
|
|
} command[] = {
|
|
{ "psreset"," ", cmd_psreset, "Download PS files and Reset Target" },
|
|
{ "reset"," ", cmd_reset, "Reset Target" },
|
|
{ "rba"," ", cmd_rba, "Read BD Address" },
|
|
{ "wba","<bdaddr> ", cmd_wba, "Write BD Address" },
|
|
{ "edutm"," ", cmd_edutm, "Enter DUT Mode" },
|
|
{ "wsm","<mode> ", cmd_wsm, "Write Scan Mode" },
|
|
{ "mb"," ", cmd_mb, "Enter Master Blaster Mode" },
|
|
{ "mbr","<address> <length> ", cmd_mbr, "Block memory read" },
|
|
{ "peek","<address> <width> ", cmd_peek, "Read Value of an Address" },
|
|
{ "poke","<address> <value> <mask> <width> ", cmd_poke, "Write Value to an Address" },
|
|
{ "cwtx","<channel number> ", cmd_cwtx, "Enter Continuous wave Tx" },
|
|
{ "cwrx","<channel number> ", cmd_cwrx, "Enter Continuous wave Rx" },
|
|
{ "rpst","<length> <id> ", cmd_rpst, "Read PS Tag" },
|
|
{ "wpst","<length> <id> <data> ", cmd_wpst, "Write PS Tag" },
|
|
{ "psr"," ", cmd_psr, "PS Reset" },
|
|
{ "setap","<storage medium> <priority>", cmd_setap, "Set Access Priority" },
|
|
{ "setam","<storage medium> <access mode>", cmd_setam, "Set Access Mode" },
|
|
{ "rpsraw","<offset> <length> ", cmd_rpsraw, "Read Raw PS" },
|
|
{ "wpsraw","<offset> <length> <data>", cmd_wpsraw, "Write Raw PS" },
|
|
{ "ssm","<disable|enable> ", cmd_ssm, "Set Sleep Mode" },
|
|
{ "dtx"," ", cmd_dtx, "Disable TX" },
|
|
{ "dump","<option> ", cmd_dump, "Display Host Controller Information" },
|
|
{ "rafh","<connection handle> ", cmd_rafh, "Read AFH channel Map" },
|
|
{ "safh","<channel classification> ", cmd_safh, "Set AFH Host Channel Classification" },
|
|
{ "wotp", "<address> <data> [length=1]", cmd_wotp, "Write Length (default 1) bytes of Data to OTP started at Address" },
|
|
{ "rotp", "<address> [length=1]", cmd_rotp, "Read Length (default 1) bytes of Data to OTP started at Address" },
|
|
{ "otp", "[dump|imp|exp|test|rpid|wpid|rvid|wvid|rba|wba|hid|cpw|pwridx|ledo] [file]; opt wba <BdAddr>",
|
|
cmd_otp, "Misc OTP operation: dump/import otp content; imp file content into otp; test otp; otp wba <BdAddr>" },
|
|
{ "plb", "[1|0]", cmd_plb, "Enable/disable PCM CODEC loopback" },
|
|
{ "psw", "[1|0] [Frequency]", cmd_psw, "Enable/disable PCM sine wave playback at frequency (0..3700)" },
|
|
{ "lert", "<rx_channel>", cmd_lert, "Put unit in LE RX mode at rx_channel (0..39)" },
|
|
{ "lett", "<tx_channel> <length> <packet_payload>", cmd_lett, "Put unit in LE TX mode at tx_channel (0..39) with packet of given length (0..37) and packet_payload" },
|
|
{ "lete", " ", cmd_lete, "End LE test" },
|
|
{ "tput-s", "[BD_Addr] [Judgment value] Logfile times data_size", cmd_tputs, "Throughput test - sender side" },
|
|
{ "tput-r", " ", cmd_tputr, "Throughput test - receiver side" },
|
|
{ NULL, NULL, 0 }
|
|
};
|
|
/*
|
|
{ "get_id", cmd_gid, "Get Chip Identification Number" },
|
|
*/
|
|
static void usage(void)
|
|
{
|
|
int i;
|
|
|
|
printf("btconfig - BTCONFIG Tool ver %s\n", VERSION);
|
|
printf("Usage:\n"
|
|
"\tbtconfig [options] <command> [command parameters]\n");
|
|
printf("Options:\n"
|
|
"\t--help\tDisplay help\n"
|
|
"\t-i dev\tHCI device\n");
|
|
printf("Commands:\n");
|
|
for (i = 0; command[i].cmd; i++)
|
|
printf("\t%-8s %-40s\t%s\n", command[i].cmd,command[i].cmd_option,command[i].doc);
|
|
printf("\n"
|
|
"For more information on the usage of each command use:\n"
|
|
"\tbtconfig <command> --help\n" );
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int opt, i, dev_id = -1;
|
|
bdaddr_t ba;
|
|
|
|
while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
|
|
switch (opt) {
|
|
case 'i':
|
|
dev_id = hci_devid(optarg);
|
|
if (dev_id < 0) {
|
|
perror("Invalid device");
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 'h':
|
|
default:
|
|
usage();
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
argc -= optind;
|
|
argv += optind;
|
|
optind = 0;
|
|
|
|
if (argc < 1) {
|
|
usage();
|
|
exit(0);
|
|
}
|
|
|
|
if (dev_id != -1 && hci_devba(dev_id, &ba) < 0) {
|
|
perror("Device is not available");
|
|
exit(1);
|
|
}
|
|
|
|
for (i = 0; command[i].cmd; i++) {
|
|
if (strcmp(command[i].cmd, argv[0]))
|
|
continue;
|
|
command[i].func(dev_id, argc, argv);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// MAster BLaster fucntions
|
|
tMasterBlasterField MasterBlasterMenu[] =
|
|
{
|
|
{"ContRxMode", "n", "toggle coNtinuous Rx", 0, ContRxModeOption, SetMasterBlasterContRxMode},
|
|
{"ContTxMode", "c", "toggle Continuous Tx", 0, ContTxModeOption, SetMasterBlasterContTxMode},
|
|
{"LERxMode", "q", "toggle LE Rx mode", 0, ContRxModeOption, SetMasterBlasterLERxMode},
|
|
{"LETxMode", "w", "toggle LE Tx mode", 0, ContTxModeOption, SetMasterBlasterLETxMode},
|
|
{"LETxPktPayload", "y", "set LE Tx packet payload", 0, LETxPktPayloadOption, SetMasterBlasterLETxPktPayload},
|
|
{"ContTxType", "u", "toggle continUous Tx Type", Cont_Tx_Raw_1MHz, ContTxTypeOption, SetMasterBlasterContTxType},
|
|
{"TestMode", "m", "toggle test Mode", eBRM_TestMode_TX_1010, TestModeOption, SetMasterBlasterTestMode},
|
|
{"HopMode", "h", "toggle Hop mode", 0, HopModeOption, SetMasterBlasterHopMode},
|
|
{"TxFreq", "t", "set Tx freq", 39, NULL, SetMasterBlasterTxFreq},
|
|
{"RxFreq", "r", "set Rx freq", 39, NULL, SetMasterBlasterRxFreq},
|
|
{"PacketType", "p", "toggle Packet type", TxTest_PktType_DH1, PacketTypeOption, SetMasterBlasterPacketType},
|
|
{"DataLen", "l", "set data Length", 15, NULL, SetMasterBlasterDataLen},
|
|
{"Power", "o", "toggle pOwer", 9, NULL, SetMasterBlasterPower},
|
|
{"BdAddr", "a", "set bdAddr", 0, NULL, SetMasterBlasterBdAddr},
|
|
{"SetBERType", "k", "set BER type", eBRM_BERMode_ALL_DATA, BERPacketTypeOption,SetMasterBlasterBERType},
|
|
{"GetBER", "g", "get BER type", 0, NULL, SetMasterBlasterNothing},
|
|
{"EnableRxTest", "d", "Enable rx test mode", 0, NULL, SetMasterBlasterNothing},
|
|
{"EnableTxTest", "e", "Enable tx test mode", 0, NULL, SetMasterBlasterNothing},
|
|
{"EnableTest", "j", "Start test mode", 0, NULL, SetMasterBlasterNothing},
|
|
{"StopTest", "s", "Stop test mode", 0, NULL, SetMasterBlasterNothing},
|
|
{"Exit", "x", "eXit", 0, NULL, SetMasterBlasterBdAddr},
|
|
{"ExitWithoutReset", "b", "Exit without reset", 0, NULL, SetMasterBlasterNothing},
|
|
};
|
|
|
|
tPsSysCfgTransmitPowerControlTable TpcTable;
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void InitMasterBlaster (tBRM_Control_packet *MasterBlaster, bdaddr_t *BdAddr, UCHAR *SkipRxSlot)
|
|
{
|
|
*SkipRxSlot = 0x01;
|
|
MasterBlaster->testCtrl.Mode = MasterBlasterMenu[TM].Default;
|
|
MasterBlaster->testCtrl.HopMode = MasterBlasterMenu[HM].Default;
|
|
MasterBlaster->testCtrl.Packet = MasterBlasterMenu[PT].Default;
|
|
MasterBlaster->testCtrl.TxFreq = MasterBlasterMenu[TF].Default;
|
|
MasterBlaster->testCtrl.RxFreq = MasterBlasterMenu[RF].Default;
|
|
MasterBlaster->testCtrl.Power = MasterBlasterMenu[PO].Default;
|
|
MasterBlaster->testCtrl.DataLen = MasterBlasterMenu[DL].Default;
|
|
MasterBlaster->ContTxMode = MasterBlasterMenu[CT].Default;
|
|
MasterBlaster->ContTxType = MasterBlasterMenu[CX].Default;
|
|
MasterBlaster->ContRxMode = MasterBlasterMenu[CR].Default;
|
|
MasterBlaster->BERType = MasterBlasterMenu[SB].Default;
|
|
MasterBlaster->LERxMode = MasterBlasterMenu[LR].Default;
|
|
MasterBlaster->LETxMode = MasterBlasterMenu[LT].Default;
|
|
MasterBlaster->LETxParms.PktPayload = MasterBlasterMenu[LTM].Default;
|
|
memcpy(MasterBlaster->bdaddr,&BdAddr->b[0],6);
|
|
|
|
TpcTable.NumOfEntries = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int CheckField (tBRM_Control_packet MasterBlaster, char *FieldAlias)
|
|
{
|
|
if (((!strncmp(FieldAlias,MasterBlasterMenu[HM].Alias,1)) && MasterBlaster.ContTxMode) ||
|
|
(((!strncmp(FieldAlias,MasterBlasterMenu[TF].Alias,1)) || (!strncmp(FieldAlias,MasterBlasterMenu[RF].Alias,1))) && MasterBlaster.testCtrl.HopMode == 1) ||
|
|
((!strncmp(FieldAlias,MasterBlasterMenu[CX].Alias,1)) && MasterBlaster.ContTxMode == 0))
|
|
{
|
|
return INVALID_MASTERBLASTER_FIELD;
|
|
}
|
|
int i;
|
|
for (i = 0; i < sizeof(MasterBlasterMenu)/sizeof(tMasterBlasterField); ++i)
|
|
{
|
|
if (!strncmp(FieldAlias,MasterBlasterMenu[i].Alias,1))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return INVALID_MASTERBLASTER_FIELD;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int GetTestModeOptionIndex (int Value)
|
|
{
|
|
int i;
|
|
for (i = 0; i < sizeof(TestModeOption)/sizeof(tMasterBlasterOption); ++i)
|
|
{
|
|
if (Value == TestModeOption[i].Value)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
// assert (0);
|
|
return -1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int GetPacketTypeOptionIndex (int Value)
|
|
{
|
|
int i;
|
|
for (i = 0; i < sizeof(PacketTypeOption)/sizeof(tMasterBlasterOption); ++i)
|
|
{
|
|
if (Value == PacketTypeOption[i].Value)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
//assert (0);
|
|
return -1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void PrintMasterBlasterMenu(tBRM_Control_packet *MasterBlaster)
|
|
{
|
|
int i;
|
|
printf ("\n---------- Master Blaster Mode ----------\n\n");
|
|
for (i = 0; i < sizeof(MasterBlasterMenu)/sizeof(tMasterBlasterField); ++i)
|
|
{
|
|
if (((i == HM || i == RF) && (MasterBlaster->ContTxMode == ENABLE)) ||
|
|
((i == TF || i == RF) && (MasterBlaster->testCtrl.HopMode == 1)) ||
|
|
((i == CX) && (MasterBlaster->ContTxMode == DISABLE)) ||
|
|
((i == CX || i == HM || i == TF || i == PT || i == DL || i == PO || i == BA) &&
|
|
(MasterBlaster->ContRxMode == ENABLE)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
printf ("\t%s - %s\n", MasterBlasterMenu[i].Alias, MasterBlasterMenu[i].Usage);
|
|
}
|
|
printf ("\n-----------------------------------------\n\n");
|
|
|
|
char BdAddr[18];
|
|
//strcpy(MasterBlaster.bdaddr,BdAddr);
|
|
|
|
printf ("ContRxMode: %s\n", ContRxModeOption[MasterBlaster->ContRxMode].Name);
|
|
printf ("ContTxMode: %s\n", ContTxModeOption[MasterBlaster->ContTxMode].Name);
|
|
printf ("LERxMode: %s\n", ContTxModeOption[MasterBlaster->LERxMode].Name);
|
|
printf ("LETxMode: %s\n", ContTxModeOption[MasterBlaster->LETxMode].Name);
|
|
|
|
// LE Rx mode
|
|
if (MasterBlaster->LERxMode == ENABLE)
|
|
{
|
|
if (MasterBlaster->testCtrl.RxFreq > MB_MAX_FREQUENCY_LE)
|
|
MasterBlaster->testCtrl.RxFreq = MB_MAX_FREQUENCY_LE;
|
|
printf("RxFreq: %d\n", MasterBlaster->testCtrl.RxFreq);
|
|
}
|
|
// LE Tx mode
|
|
if (MasterBlaster->LETxMode == ENABLE)
|
|
{
|
|
if (MasterBlaster->testCtrl.DataLen > MB_MAX_DATALEN_LE)
|
|
MasterBlaster->testCtrl.DataLen = MB_MAX_DATALEN_LE;
|
|
printf("TxFreq: %d\n", MasterBlaster->testCtrl.TxFreq);
|
|
printf("DataLen: %d\n", MasterBlaster->testCtrl.DataLen);
|
|
printf("PktPayload: %s\n", LETxPktPayloadOption[MasterBlaster->LETxParms.PktPayload].Name);
|
|
}
|
|
// Continous Rx mode
|
|
else if (MasterBlaster->ContRxMode == ENABLE)
|
|
{
|
|
printf ("BER Type: %s\n",BERPacketTypeOption[MasterBlaster->BERType].Name);
|
|
printf ("RxFreq: %d\n", MasterBlaster->testCtrl.RxFreq);
|
|
}
|
|
// Continous Tx mode and Tx test mode
|
|
else
|
|
{
|
|
printf ("BER Type: %s\n",BERPacketTypeOption[MasterBlaster->BERType].Name);
|
|
if (MasterBlaster->ContTxMode == ENABLE)
|
|
{
|
|
printf ("ContTxType: %s\n", ContTxTypeOption[MasterBlaster->ContTxType].Name);
|
|
if (ContTxTypeOption[MasterBlaster->ContTxType].Value != CW_Single_Tone)
|
|
printf ("TestMode: %s\n", TestModeOption[GetTestModeOptionIndex(MasterBlaster->testCtrl.Mode)].Name);
|
|
printf ("TxFreq: %d\n", MasterBlaster->testCtrl.TxFreq);
|
|
}
|
|
else
|
|
{
|
|
printf ("TestMode: %s\n", TestModeOption[GetTestModeOptionIndex(MasterBlaster->testCtrl.Mode)].Name);
|
|
printf ("HopMode: %s\n", HopModeOption[MasterBlaster->testCtrl.HopMode].Name);
|
|
|
|
if (MasterBlaster->testCtrl.HopMode == 0)
|
|
{
|
|
printf ("TxFreq: %d\n", MasterBlaster->testCtrl.TxFreq);
|
|
printf ("RxFreq: %d\n", MasterBlaster->testCtrl.RxFreq);
|
|
}
|
|
}
|
|
if (TpcTable.NumOfEntries > 0)
|
|
{
|
|
printf ("Power: Step = %d/%d; Level = %d dBm\n", MasterBlaster->testCtrl.Power+1,
|
|
TpcTable.NumOfEntries, TpcTable.t[MasterBlaster->testCtrl.Power].TxPowerLevel);
|
|
}
|
|
else
|
|
{
|
|
printf ("Power: Step = Max; Level = N/A\n");
|
|
}
|
|
if ((MasterBlaster->ContTxMode == ENABLE && ContTxTypeOption[MasterBlaster->ContTxType].Value == Cont_Tx_Regular) ||
|
|
(MasterBlaster->ContTxMode == DISABLE))
|
|
{
|
|
printf ("PacketType: %s\n", PacketTypeOption[GetPacketTypeOptionIndex(MasterBlaster->testCtrl.Packet)].Name);
|
|
printf ("DataLen: %d\n", MasterBlaster->testCtrl.DataLen);
|
|
}
|
|
if (ContTxTypeOption[MasterBlaster->ContTxType].Value != CW_Single_Tone) {//for single tone, no bdaddr
|
|
ba2str((const bdaddr_t *)MasterBlaster->bdaddr, BdAddr);
|
|
printf ("BdAddr: 0x%s\n\n",BdAddr);
|
|
}
|
|
}
|
|
printf ("\nmb>");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterTestMode(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = (int)MasterBlaster->testCtrl.Mode;
|
|
|
|
if (ToggleOption (&Value, Option, TestModeOption,
|
|
sizeof(TestModeOption)/sizeof(tMasterBlasterOption), TM,1))
|
|
{
|
|
MasterBlaster->testCtrl.Mode = (UCHAR)Value;
|
|
// Enable continuous Tx should disable continuous Rx
|
|
MasterBlaster->ContRxMode = DISABLE;
|
|
MasterBlaster->ContTxMode = DISABLE;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterHopMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = (int)MasterBlaster->testCtrl.HopMode;
|
|
|
|
if (ToggleOption (&Value, Option, HopModeOption,
|
|
sizeof(HopModeOption)/sizeof(tMasterBlasterOption), HM,1))
|
|
{
|
|
MasterBlaster->testCtrl.HopMode = (UCHAR)Value;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterTxFreq (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
//char Buffer[20];
|
|
tMasterBlasterOption NewValue;
|
|
int LoopCount = 4;
|
|
int Value = (int)MasterBlaster->testCtrl.TxFreq;
|
|
int MaxFreq = LEMode ? MB_MAX_FREQUENCY_LE : MB_MAX_FREQUENCY;
|
|
int MinFreq = LEMode ? MB_MIN_FREQUENCY_LE : MB_MIN_FREQUENCY;
|
|
|
|
while (--LoopCount > 0)
|
|
{
|
|
printf ("\n Enter Tx frequency (%d..%d): ", MinFreq, MaxFreq);
|
|
scanf("%d",&NewValue.Value);
|
|
// fgets(NewValue,3,stdin);
|
|
if (MinMaxOption (&Value, &NewValue, MinFreq, MaxFreq))
|
|
{
|
|
MasterBlaster->testCtrl.TxFreq = (UCHAR)Value;
|
|
return TRUE;
|
|
}
|
|
else if (LoopCount > 1)
|
|
{
|
|
printf ("\n ERROR ---> Invalid Tx frequency.\n");
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterRxFreq (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
tMasterBlasterOption NewValue;
|
|
int LoopCount = 4;
|
|
int Value = (int)MasterBlaster->testCtrl.RxFreq;
|
|
int MaxFreq = LEMode ? MB_MAX_FREQUENCY_LE : MB_MAX_FREQUENCY;
|
|
int MinFreq = LEMode ? MB_MIN_FREQUENCY_LE : MB_MIN_FREQUENCY;
|
|
|
|
while (--LoopCount > 0)
|
|
{
|
|
printf ("\n Enter Rx frequency (%d..%d): ", MinFreq, MaxFreq);
|
|
scanf("%d",&NewValue.Value);
|
|
if (MinMaxOption (&Value, &NewValue, MinFreq, MaxFreq))
|
|
{
|
|
MasterBlaster->testCtrl.RxFreq = (UCHAR)Value;
|
|
return TRUE;
|
|
}
|
|
else if (LoopCount > 1)
|
|
{
|
|
printf ("\n ERROR ---> Invalid Rx frequency.\n");
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterPacketType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = (int)MasterBlaster->testCtrl.Packet;
|
|
|
|
if (ToggleOption (&Value, Option, PacketTypeOption,
|
|
sizeof(PacketTypeOption)/sizeof(tMasterBlasterOption), PT,1))
|
|
{
|
|
MasterBlaster->testCtrl.Packet = (UCHAR)Value;
|
|
MasterBlaster->testCtrl.DataLen = MaxDataLenOption[GetPacketTypeOptionIndex(Value)];
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterDataLen (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
tMasterBlasterOption NewValue;
|
|
int LoopCount = 4;
|
|
int MaxLen = LEMode ? MB_MAX_DATALEN_LE : MB_MAX_DATALEN;
|
|
int MinLen = LEMode ? MB_MIN_DATALEN_LE : MB_MIN_DATALEN;
|
|
|
|
while (--LoopCount > 0)
|
|
{
|
|
printf ("\n Enter data length (%d..%d): ", MinLen, MaxLen);
|
|
scanf("%d",&NewValue.Value);
|
|
if (MinMaxOption (&MasterBlaster->testCtrl.DataLen, &NewValue, MinLen, MaxLen))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else if (LoopCount > 1)
|
|
{
|
|
printf ("\n ERROR ---> Invalid data length.\n");
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterPower (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
if (TpcTable.NumOfEntries > MAX_TRANSMIT_POWER_CONTROL_ENTRIES)
|
|
{
|
|
printf ("\nNumber of entries in TPC table exceeds the limit.\n");
|
|
sleep(3);
|
|
return TRUE;
|
|
}
|
|
|
|
if (TpcTable.NumOfEntries == 0)
|
|
{
|
|
printf ("\nThere is no entry in TPC table.\n");
|
|
sleep(3);
|
|
return TRUE;
|
|
}
|
|
|
|
int Value = (int)MasterBlaster->testCtrl.Power;
|
|
|
|
if (Option == NULL) return TRUE;
|
|
if (ToggleMinMaxOption (&Value, Option, PO, 0, TpcTable.NumOfEntries-1,1))
|
|
{
|
|
MasterBlaster->testCtrl.Power = (UCHAR)Value;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterBdAddr (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
//char Buffer[20];
|
|
tMasterBlasterOption NewValue;
|
|
bdaddr_t bdaddr;
|
|
|
|
printf ("\n Enter BdAddr: ");
|
|
scanf("%s",NewValue.Name);
|
|
str2ba(NewValue.Name,&bdaddr);
|
|
strncpy((char *) MasterBlaster->bdaddr,(char *) bdaddr.b,6);
|
|
return TRUE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterContTxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = (int)MasterBlaster->ContTxMode;
|
|
|
|
if (ToggleOption (&Value, Option, ContTxModeOption,
|
|
sizeof(ContTxModeOption)/sizeof(tMasterBlasterOption), CT,1))
|
|
{
|
|
MasterBlaster->ContTxMode = (UCHAR)Value;
|
|
if (MasterBlaster->ContTxMode == ENABLE)
|
|
{
|
|
// Enable continuous Tx should disable continuous Rx
|
|
MasterBlaster->ContRxMode = DISABLE;
|
|
MasterBlaster->LERxMode = DISABLE;
|
|
MasterBlaster->LETxMode = DISABLE;
|
|
LEMode = FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterContTxType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = (int)MasterBlaster->ContTxType;
|
|
|
|
if (ToggleOption (&Value, Option, ContTxTypeOption,
|
|
sizeof(ContTxTypeOption)/sizeof(tMasterBlasterOption), CX,1))
|
|
{
|
|
MasterBlaster->ContTxType = (UCHAR)Value;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterLERxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = MasterBlaster->LERxMode;
|
|
|
|
if (ToggleOption (&Value, Option, ContRxModeOption,
|
|
sizeof(ContRxModeOption)/sizeof(tMasterBlasterOption), LR, 1))
|
|
{
|
|
MasterBlaster->LERxMode = (UCHAR)Value;
|
|
if (MasterBlaster->LERxMode == ENABLE)
|
|
{
|
|
/* Enable continuous Tx should disable other modes */
|
|
MasterBlaster->LETxMode = DISABLE;
|
|
MasterBlaster->ContTxMode = DISABLE;
|
|
MasterBlaster->ContRxMode = DISABLE;
|
|
if (MasterBlaster->testCtrl.RxFreq > 39)
|
|
{
|
|
MasterBlaster->testCtrl.RxFreq = 39;
|
|
}
|
|
LEMode = TRUE;
|
|
}
|
|
else
|
|
{
|
|
LEMode = FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterLETxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = MasterBlaster->LETxMode;
|
|
|
|
if (ToggleOption (&Value, Option, ContTxModeOption,
|
|
sizeof(ContTxModeOption)/sizeof(tMasterBlasterOption), LT, 1))
|
|
{
|
|
MasterBlaster->LETxMode = (UCHAR)Value;
|
|
if (MasterBlaster->LETxMode == ENABLE)
|
|
{
|
|
/* Enable continuous Tx should disable other modes */
|
|
MasterBlaster->LERxMode = DISABLE;
|
|
MasterBlaster->ContTxMode = DISABLE;
|
|
MasterBlaster->ContRxMode = DISABLE;
|
|
if (MasterBlaster->testCtrl.TxFreq > MB_MAX_FREQUENCY_LE)
|
|
{
|
|
MasterBlaster->testCtrl.TxFreq = 39;
|
|
}
|
|
LEMode = TRUE;
|
|
}
|
|
else
|
|
{
|
|
LEMode = FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterLETxPktPayload(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = MasterBlaster->LETxParms.PktPayload;
|
|
|
|
if (ToggleOption(&Value, Option, LETxPktPayloadOption,
|
|
sizeof(LETxPktPayloadOption)/sizeof(tMasterBlasterOption), LTM, 1))
|
|
{
|
|
MasterBlaster->LETxParms.PktPayload = (UCHAR)Value;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterContRxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = (int)MasterBlaster->ContRxMode;
|
|
printf("\n N op\n");
|
|
if (ToggleOption (&Value, Option, ContRxModeOption,
|
|
sizeof(ContRxModeOption)/sizeof(tMasterBlasterOption), CR,1))
|
|
{
|
|
MasterBlaster->ContRxMode = (UCHAR)Value;
|
|
if (MasterBlaster->ContRxMode == ENABLE)
|
|
{
|
|
// Enable continuous Tx should disable continuous Rx
|
|
MasterBlaster->ContTxMode = DISABLE;
|
|
MasterBlaster->LERxMode = DISABLE;
|
|
MasterBlaster->LETxMode = DISABLE;
|
|
LEMode = FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int SetMasterBlasterBERType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
int Value = (int)MasterBlaster->BERType;
|
|
if (ToggleOption (&Value, Option, BERPacketTypeOption,
|
|
sizeof(BERPacketTypeOption)/sizeof(tMasterBlasterOption), SB, 1))
|
|
{
|
|
MasterBlaster->BERType = (UCHAR)Value;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int SetMasterBlasterNothing (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option)
|
|
{
|
|
UNUSED(MasterBlaster);
|
|
UNUSED(Option);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int ToggleOption (int *Value, tMasterBlasterOption *Option, tMasterBlasterOption *OptionArray,
|
|
int Size, int FieldID, int Step)
|
|
{
|
|
char Opt = Option->Name[0];
|
|
|
|
int Backward = ((Opt - 'A' + 'a') == MasterBlasterMenu[FieldID].Alias[0]);
|
|
int i;
|
|
for (i = 0; i < Size; ++i)
|
|
{
|
|
if (*Value == OptionArray[i].Value)
|
|
{
|
|
if (Backward)
|
|
{
|
|
i = ((i - Step) < 0) ? (Size - Step + i) : (i - Step);
|
|
}
|
|
else
|
|
{
|
|
i = (i + Step) % Size;
|
|
}
|
|
*Value = OptionArray[i].Value;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int MinMaxOption (int *Value, tMasterBlasterOption *Option, int Min, int Max)
|
|
{
|
|
int NewValue = Option->Value;
|
|
|
|
if (NewValue < Min || NewValue > Max)
|
|
{
|
|
return FALSE;
|
|
}
|
|
*Value = NewValue;
|
|
return TRUE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
int ToggleMinMaxOption (int *Value, tMasterBlasterOption *Option, int FieldID, int Min, int Max, int Step)
|
|
{
|
|
char Opt = Option->Name[0];
|
|
int Backward = ((Opt - 'A' + 'a') == MasterBlasterMenu[FieldID].Alias[0]);
|
|
|
|
if (Backward)
|
|
{
|
|
*Value = ((*Value - Step) < Min) ? (Max + 1 - (Step - (*Value - Min))) : (*Value - Step);
|
|
}
|
|
else
|
|
{
|
|
*Value = ((*Value + Step) > Max) ? (Min + (Step - (Max + 1 - *Value))) : (*Value + Step);
|
|
}
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|