/* | |
* 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 <linux/types.h> | |
#include <netinet/in.h> | |
#include <netinet/tcp.h> | |
#include <bluetooth/bluetooth.h> | |
#include <bluetooth/hci.h> | |
#include <bluetooth/hci_lib.h> | |
#include "compat/getline.h" | |
#include "btconfig.h" | |
#include "masterblaster.h" | |
#define BT_PORT 2398 | |
/* Global Variables */ | |
static int sid, cid, aid; | |
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; | |
} | |
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; | |
} | |
/* 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 newfd, FieldNum,dd,iRet,need_raw, iDataSize, address,width,value,mask, fdmax, k, l; | |
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; | |
fd_set master, read_fds; | |
uint32_t m_BerTotalBits, m_BerGoodBits; | |
uint8_t m_pattern[16]; | |
uint16_t m_pPatternlength; | |
struct hci_filter flt; | |
struct hci_dev_info di; | |
struct timeval timeout; | |
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); | |
m_BerGoodBits = 0; | |
m_BerTotalBits = 0; | |
m_pattern[0] = 0x0f; | |
m_pPatternlength = 1; | |
FD_ZERO(&master); | |
FD_ZERO(&read_fds); | |
FD_SET(0, &master); | |
fdmax = 0; | |
newfd = -1; | |
while (1) { | |
read_fds = master; | |
timeout.tv_sec = 5; | |
timeout.tv_usec = 0; | |
iRet = select(fdmax+1, &read_fds, NULL, NULL, &timeout); | |
if (iRet == -1) { | |
perror("cmd_mb select() error!"); | |
goto exits_mb; | |
} | |
if (iRet == 0) continue; | |
for(i = 0; i <= fdmax; i++) { | |
if(FD_ISSET(i, &read_fds)) { | |
if (i==0) { // input | |
scanf("%s",buf); | |
FieldAlias = (char)buf[0]; | |
FieldNum = CheckField(MasterBlaster, &FieldAlias); | |
if (FieldNum == INVALID_MASTERBLASTER_FIELD) { | |
printf ("\nERROR ---> Invalid command. Try again.\n"); | |
printf ("mb>"); | |
continue; | |
} | |
if (!strncmp(&FieldAlias, MasterBlasterMenu[EXX].Alias, 1)) { | |
printf("\nExit the Master Blaster Mode without reset\n"); | |
goto exits_mb; | |
} | |
// if the test is in rx and the key is neither 'd' nor 'g', then stop the test, renew the option, and procced | |
// if the test is in tx and the key is not 'e', then stop the test, renew the option, and procced | |
// if the test is in (LE) continuous rx/tx and the key is not 'j' , then stop the test, renew the option, and procced | |
if (((TestEnabled == MB_RX_TEST) && strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1) && strncmp(&FieldAlias, MasterBlasterMenu[GB].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; | |
} | |
if (TestEnabled == MB_RX_TEST) { | |
if (need_raw) { | |
if (ioctl(dd, HCISETRAW, 0) < 0) | |
perror("Can't clear raw mode \n"); | |
} | |
FD_CLR(newfd, &master); | |
newfd = -1; | |
fdmax = 0; | |
} | |
// Ok = Diag::Reset (Unit, ""); | |
//PSInit(dd); | |
// The default setting is sleep mode enabled. | |
memset(&buf,0,sizeof(buf)); | |
buf[0] = 1; | |
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]); | |
} | |
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)) { // Exit | |
TestEnabled = MB_NO_TEST; | |
printf ("\n Exit ..\n"); | |
goto exits_mb; | |
} else if (!strncmp(&FieldAlias,MasterBlasterMenu[ST].Alias,1)) { // Stop Test | |
TestEnabled = MB_NO_TEST; | |
PrintMasterBlasterMenu (&MasterBlaster); | |
continue; | |
} else if (!strncmp(&FieldAlias,MasterBlasterMenu[GB].Alias,1)) { // get BER | |
printf("\n\tGoodBits %d, total is %d\n", m_BerGoodBits, m_BerTotalBits); | |
printf("mb>\n"); | |
continue; | |
} else if (!strncmp(&FieldAlias,MasterBlasterMenu[PO].Alias,1)) { // set Power | |
MasterBlasterMenu[FieldNum].pFunc (&MasterBlaster, &FieldAlias); | |
} else if (!MasterBlasterMenu[FieldNum].pFunc (&MasterBlaster, MasterBlasterMenu[FieldNum].Options)) { | |
printf ("\nERROR ---> Invalid option. Try again.\n"); | |
printf ("mb>"); | |
continue; | |
} | |
PrintMasterBlasterMenu(&MasterBlaster); | |
// Enable RX test mode | |
if ((!strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1) && (TestEnabled == MB_NO_TEST)) | |
|| (strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1) && (TestEnabled == MB_RX_TEST))) { | |
Ok = Dut(dd); | |
if (!Ok) { | |
printf("\nERROR ---> Could not enter DUT mode\n"); | |
printf("mb>"); | |
continue; | |
} | |
printf("."); | |
if (hci_devinfo(dev_id, &di) < 0) { | |
printf("Can't get device info\n"); | |
printf("mb>"); | |
continue; | |
} | |
need_raw = !hci_test_bit(HCI_RAW, &di.flags); | |
memset(&buf,0,HCI_MAX_EVENT_SIZE); | |
buf[0] = eBRM_TestMode_Rx; | |
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_RX_TESTER, 15, buf); | |
if (buf[6] != 0) { | |
printf("\nRx 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(" rx test is in progress. Press 's' to stop the test\n"); | |
TestEnabled = MB_RX_TEST; | |
hci_filter_clear(&flt); | |
hci_filter_all_ptypes(&flt); | |
hci_filter_all_events(&flt); | |
if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { | |
printf("Can't set filter for hci\n"); | |
printf("mb>"); | |
continue; | |
} | |
if (need_raw) { | |
if (ioctl(dd, HCISETRAW, 1) < 0) { | |
printf("Can't set raw mode on hci\n"); | |
printf("mb>"); | |
continue; | |
} | |
} | |
newfd = dd; | |
FD_SET(newfd, &master); | |
fdmax = dd; | |
} | |
printf("mb>"); | |
continue; | |
} else if ((!strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1)) && (TestEnabled == MB_RX_TEST)) { | |
printf(" rx test is in progress. Press 's' to stop the test\n"); | |
printf("mb>"); | |
continue; | |
} | |
// 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("\nTx 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(" tx 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(" tx 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; | |
} | |
} | |
else if (i == newfd) { | |
iRet = read(i, buf, sizeof(buf)); | |
iDataSize = iRet - 5; | |
// printf("first:%x,nbyte:%d, packet:%d, pattern:%x\n",buf[0], iRet, (uint16_t)(buf[3] | (buf[4] << 8)), buf[5]); | |
if (buf[0] == 0x2) { // ACL data | |
m_BerTotalBits = m_BerTotalBits + iDataSize * 8; | |
for(j=0,l=0;j<iDataSize;j++,l++) { | |
if (l == m_pPatternlength) l = 0; | |
for(k=0;k<8;k++){ | |
if((m_pattern[l]&(1<<k)) == (buf[8+j]&(1<<k))) | |
m_BerGoodBits++; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
exits_mb: | |
if (need_raw) { | |
if (ioctl(dd, HCISETRAW, 0) < 0) | |
perror("Can't clear raw mode \n"); | |
} | |
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]; | |
int 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] = (UCHAR)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) | |
{ | |
UINT32 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 sucessful!\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) | |
{ | |
UINT32 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]); | |
} | |
} | |
static const char *plb_help = | |
"\nUsage:" | |
"\nplb [1|0]\n" | |
"\nplb 1\n" | |
"\n\n"; | |
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); | |
} | |
static const char *psw_help = | |
"\nUsage:" | |
"\npsw [1|0] [Frequency]\n" | |
"\npsw 1 3000\n" | |
"\n\n"; | |
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; | |
} | |
static const char *lete_help = | |
"\nUsage:" | |
"\nlete\n" | |
"\n\n"; | |
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 cleanup() | |
{ | |
if (cid>=0) { | |
close(cid); | |
} | |
if (sid>=0) { | |
close(sid); | |
} | |
} | |
int sock_recv(int sockid, unsigned char *buf, int buflen) | |
{ | |
int recvbytes; | |
recvbytes = recv(sockid, buf, buflen, 0); | |
if (recvbytes == 0) { | |
printf("Connection close!? zero bytes received\n"); | |
return -1; | |
} else if (recvbytes > 0) { | |
return recvbytes; | |
} | |
return -1; | |
} | |
int sock_send(int sockid, unsigned char *buf, int bytes) | |
{ | |
int cnt; | |
unsigned char* bufpos = buf; | |
while (bytes) { | |
cnt = write(sockid, bufpos, bytes); | |
if (cnt != bytes) | |
printf("cnt:%d,bytes:%d\n",cnt, bytes); | |
if (!cnt) { | |
break; | |
} | |
if (cnt == -1) { | |
if (errno == EINTR) { | |
continue; | |
} else { | |
return -1; | |
} | |
} | |
bytes -= cnt; | |
bufpos += cnt; | |
} | |
return (bufpos - buf); | |
} | |
static void cmd_btagent(int dev_id, int argc, char **argv) | |
{ | |
int dd, i, j, k, l, iRet, need_raw, rx_enable, iDataSize; | |
uint32_t m_BerTotalBits, m_BerGoodBits; | |
uint8_t m_pattern[16]; | |
uint16_t m_pPatternlength; | |
int port = BT_PORT; | |
struct sigaction sa; | |
unsigned char buf[1024]; | |
struct hci_filter flt; | |
struct hci_dev_info di; | |
struct timeval timeout; | |
/* master file descriptor list */ | |
fd_set master; | |
fd_set read_fds; | |
/* server address */ | |
struct sockaddr_in serveraddr; | |
int fdmax; | |
/* listening socket descriptor */ | |
int listener = -1; | |
/* newly accept()ed socket descriptor */ | |
int newfd = -1; | |
int nbytes; | |
/* for setsockopt() SO_REUSEADDR, below */ | |
int yes = 1; | |
int addrlen; | |
if (argc > 1) | |
port = atoi(argv[1]); | |
if (port == 0) | |
port = BT_PORT; | |
else if (port < 0 || port >65534) { | |
perror("\nERROR: Invalid port number\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; | |
} | |
if (hci_devinfo(dev_id, &di) < 0) { | |
perror("Can't get device info\n"); | |
hci_close_dev(dd); | |
return; | |
} | |
need_raw = !hci_test_bit(HCI_RAW, &di.flags); | |
hci_filter_clear(&flt); | |
hci_filter_all_ptypes(&flt); | |
hci_filter_all_events(&flt); | |
if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { | |
perror("Can't set filter for hci\n"); | |
hci_close_dev(dd); | |
return; | |
} | |
if (need_raw) { | |
if (ioctl(dd, HCISETRAW, 1) < 0) { | |
perror("Can't set raw mode on hci\n"); | |
hci_close_dev(dd); | |
return; | |
} | |
} | |
CtrlCBreak = FALSE; | |
memset(&sa, 0, sizeof(sa)); | |
sa.sa_handler = sig_term; | |
sigaction(SIGTERM, &sa, NULL); | |
sigaction(SIGINT, &sa, NULL); | |
/* clear the master and temp sets */ | |
FD_ZERO(&master); | |
FD_ZERO(&read_fds); | |
/* get the listener */ | |
if((listener = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { | |
perror("Server-socket() error lol!"); | |
return; | |
} | |
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(int)) == -1) { | |
perror("Server-setsockopt() error lol!"); | |
close(listener); | |
return; | |
} | |
if(setsockopt(listener, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(int)) == -1) { | |
perror("Server-setsockopt() error TCP_NODELAY\n"); | |
close(listener); | |
return; | |
} | |
/* bind */ | |
serveraddr.sin_family = AF_INET; | |
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); | |
serveraddr.sin_port = htons(port); | |
memset(&(serveraddr.sin_zero), 0, 8); | |
if(bind(listener, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1) { | |
perror("Server-bind() error lol!"); | |
close(listener); | |
return; | |
} | |
/* listen */ | |
if(listen(listener, 10) == -1) { | |
perror("Server-listen() error lol!"); | |
close(listener); | |
return; | |
} | |
/* add the listener to the master set */ | |
FD_SET(listener, &master); | |
/* add hci handler to the master set */ | |
FD_SET(dd, &master); | |
FD_SET(0, &master); | |
/* keep track of the biggest file descriptor */ | |
fdmax = listener; | |
if (dd > listener) fdmax = dd; | |
printf("Start BtAgent, press 'q' to exit.\n"); | |
rx_enable = 0; | |
m_BerGoodBits = 0; | |
m_BerTotalBits = 0; | |
m_pattern[0] = 0x0f; | |
m_pPatternlength = 1; | |
while (1) { | |
read_fds = master; | |
timeout.tv_sec = 5; | |
timeout.tv_usec = 0; | |
iRet = select(fdmax+1, &read_fds, NULL, NULL, &timeout); | |
if (iRet == -1) { | |
perror("Server-select() error lol!"); | |
if (newfd > 0) close(newfd); | |
close(listener); | |
goto exits; | |
} | |
if (CtrlCBreak) break; | |
if (iRet == 0) continue; | |
/*run through the existing connections looking for data to be read*/ | |
for(i = 0; i <= fdmax; i++) { | |
if(FD_ISSET(i, &read_fds)) { | |
if(i == 0) { | |
printf("Shutting down btagent\n"); | |
iRet = getchar(); | |
if (iRet == 'q') goto exits; | |
continue; | |
} | |
if(i == listener) { | |
/* handle new connections */ | |
addrlen = sizeof(struct sockaddr_in); | |
if((newfd = accept(listener, (struct sockaddr *)&serveraddr, &addrlen)) == -1) { | |
perror("Server-accept() error lol!"); | |
goto exits; | |
} | |
else { | |
printf("Server-accept() is OK...%d\n",newfd); | |
FD_SET(newfd, &master); /* add to master set */ | |
if(newfd > fdmax) | |
fdmax = newfd; | |
} | |
} | |
else if (i == newfd) { | |
/* handle data from a client */ | |
if((nbytes = sock_recv(i, buf, sizeof(buf))) < 0) { | |
/* got error or connection closed by client */ | |
close(i); | |
/* remove from master set */ | |
FD_CLR(i, &master); | |
} | |
else { | |
for (j=0; j<nbytes; j++) | |
printf("%x ",buf[j]); | |
printf("\n"); | |
if (buf[0] == 0x7) { // BTAGENT_CMD_EVENT | |
if (buf[3] == 0x01) { // BTAGENT_CMD_EVENT_GETBER | |
buf[11] = (m_BerTotalBits & 0xff000000) >> 24; | |
buf[10] = (m_BerTotalBits & 0xff0000) >> 16; | |
buf[9] = (m_BerTotalBits & 0xff00) >> 8; | |
buf[8] = m_BerTotalBits & 0xff; | |
buf[7] = (m_BerGoodBits & 0xff000000) >> 24; | |
buf[6] = (m_BerGoodBits & 0xff0000) >> 16; | |
buf[5] = (m_BerGoodBits & 0xff00) >> 8; | |
buf[4] = m_BerGoodBits & 0xff; | |
buf[3] = 1; // BTAGENT_CMD_EVENT_GETBER | |
buf[2] = 0; | |
buf[1] = 9; | |
buf[0] = 7; | |
sock_send(newfd, buf, 9+3); | |
usleep(2000); | |
} | |
else if (buf[3] == 0x02) { // BTAGENT_CMD_EVENT_PATTERN | |
m_pPatternlength = (uint16_t)(buf[1] | (buf[2] << 8)); | |
m_pPatternlength --; | |
if (m_pPatternlength > 16) m_pPatternlength = 16; | |
memcpy(m_pattern,&buf[4],m_pPatternlength); | |
printf("PatternLength:%d,%x\n",m_pPatternlength,buf[4]); | |
} | |
continue; | |
} | |
if (rx_enable == 1) { | |
if ((buf[4] == 0x03) && (buf[5] == 0x0c)) | |
rx_enable = 0; | |
} | |
write(dd, &buf[3], nbytes - 3); | |
} | |
} | |
else if (i == dd) { | |
nbytes = read(dd, &buf[3], sizeof(buf) - 3); | |
iDataSize = nbytes - 5; | |
// printf("nbyte:%d, packet:%d, pattern:%x\n",nbytes, (uint16_t)(buf[6] | (buf[7] << 8)), buf[8]); | |
if (buf[3] == 0x2) { // ACL data | |
if (rx_enable) { | |
m_BerTotalBits = m_BerTotalBits + iDataSize * 8; | |
for(j=0,l=0;j<iDataSize;j++,l++) { | |
if (l == m_pPatternlength) l = 0; | |
for(k=0;k<8;k++){ | |
if((m_pattern[l]&(1<<k)) == (buf[8+j]&(1<<k))) | |
m_BerGoodBits++; | |
} | |
} | |
} | |
} | |
else { | |
if ((buf[7] == 0x5b) && (buf[8] == 0xfc)) { // Rx start CMD's event | |
rx_enable = 1; | |
m_BerTotalBits = 0; | |
m_BerGoodBits = 0; | |
} | |
buf[2] = 0; | |
buf[1] = (uint16_t)nbytes; | |
buf[0] = 3; | |
if (newfd > 0) { | |
sock_send(newfd, buf, nbytes+3); | |
usleep(2000); | |
} | |
} | |
} | |
} | |
} | |
} | |
exits: | |
if (need_raw) { | |
if (ioctl(dd, HCISETRAW, 0) < 0) | |
perror("Can't clear raw mode \n"); | |
} | |
hci_close_dev(dd); | |
if (listener > 0) close(listener); | |
if (newfd > 0) close(newfd); | |
printf("Total:%d,Good:%d\n",m_BerTotalBits, m_BerGoodBits); | |
} | |
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" }, | |
{ "btagent","<port number>", cmd_btagent, "BT Agent for IQFact" }, | |
{ NULL, NULL, NULL, NULL } | |
}; | |
/* | |
{ "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, SetMasterBlasterNothing}, | |
{"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; | |
} | |
unsigned 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) | |
{ | |
unsigned 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) | |
{ | |
unsigned 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) | |
{ | |
unsigned 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>\n"); | |
} | |
//---------------------------------------------------------------------------- | |
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 continous Tx should disable continous 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, char *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 (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]; | |
bdaddr_t bdaddr; | |
printf ("\n Enter BdAddr: "); | |
// gets(Buffer); | |
scanf("%s",Buffer); | |
str2ba(Buffer,&bdaddr); | |
strncpy(MasterBlaster->bdaddr,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 continous Tx should disable continous 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 continous 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 continous 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 continous Tx should disable continous 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, char *Option, int FieldID, int Min, int Max, int Step) | |
{ | |
char Opt = *Option; | |
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; | |
} | |
//---------------------------------------------------------------------------- |