Index: chromeos/drivers/ath6kl/miscdrv/ar3kps/ar3kpsparser.c |
diff --git a/chromeos/drivers/ath6kl/miscdrv/ar3kps/ar3kpsparser.c b/chromeos/drivers/ath6kl/miscdrv/ar3kps/ar3kpsparser.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8392777512ec46de8621f7298f5327fae1330232 |
--- /dev/null |
+++ b/chromeos/drivers/ath6kl/miscdrv/ar3kps/ar3kpsparser.c |
@@ -0,0 +1,972 @@ |
+/* |
+ * Copyright (c) 2004-2008 Atheros Communications Inc. |
+ * All rights reserved. |
+ * |
+ * This file implements the Atheros PS and patch parser. |
+ * It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands. |
+ * |
+ * |
+ * |
+ * ar3kpsparser.c |
+ * |
+ * |
+ * |
+ * The software source and binaries included in this development package are |
+ * licensed, not sold. You, or your company, received the package under one |
+ * or more license agreements. The rights granted to you are specifically |
+ * listed in these license agreement(s). All other rights remain with Atheros |
+ * Communications, Inc., its subsidiaries, or the respective owner including |
+ * those listed on the included copyright notices.. Distribution of any |
+ * portion of this package must be in strict compliance with the license |
+ * agreement(s) terms. |
+ * |
+ * |
+ * |
+ */ |
+ |
+ |
+#include "ar3kpsparser.h" |
+ |
+#define BD_ADDR_SIZE 6 |
+#define WRITE_PATCH 8 |
+#define ENABLE_PATCH 11 |
+#define PS_RESET 2 |
+#define PS_WRITE 1 |
+#define PS_VERIFY_CRC 9 |
+#define CHANGE_BDADDR 15 |
+ |
+#define HCI_COMMAND_HEADER 7 |
+ |
+#define HCI_EVENT_SIZE 7 |
+ |
+#define WRITE_PATCH_COMMAND_STATUS_OFFSET 5 |
+ |
+#define RAM_PS_REGION (1<<0) |
+#define RAM_PATCH_REGION (1<<1) |
+#define RAMPS_MAX_PS_DATA_PER_TAG 20000 |
+#define MAX_RADIO_CFG_TABLE_SIZE 244 |
+#define RAMPS_MAX_PS_TAGS_PER_FILE 50 |
+ |
+#define PS_MAX_LEN 500 |
+#define LINE_SIZE_MAX (PS_MAX_LEN *2) |
+ |
+/* Constant values used by parser */ |
+#define BYTES_OF_PS_DATA_PER_LINE 16 |
+#define RAMPS_MAX_PS_DATA_PER_TAG 20000 |
+ |
+ |
+/* Number pf PS/Patch entries in an HCI packet */ |
+#define MAX_BYTE_LENGTH 244 |
+ |
+#define SKIP_BLANKS(str) while (*str == ' ') str++ |
+#define MIN(x, y) (((x) <= (y))? (x):(y)) |
+#define MAX(x, y) (((x) >= (y))? (x):(y)) |
+ |
+#define UNUSED(x) (x=x) |
+ |
+#define IS_BETWEEN(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) |
+#define IS_DIGIT(c) (IS_BETWEEN((c), '0', '9')) |
+#define IS_HEX(c) (IS_BETWEEN((c), '0', '9') || IS_BETWEEN((c), 'a', 'f') || IS_BETWEEN((c), 'A', 'F')) |
+#define TO_LOWER(c) (IS_BETWEEN((c), 'A', 'Z') ? ((c) - 'A' + 'a') : (c)) |
+#define IS_BLANK(c) ((c) == ' ') |
+#define CONV_DEC_DIGIT_TO_VALUE(c) ((c) - '0') |
+#define CONV_HEX_DIGIT_TO_VALUE(c) (IS_DIGIT(c) ? ((c) - '0') : (IS_BETWEEN((c), 'A', 'Z') ? ((c) - 'A' + 10) : ((c) - 'a' + 10))) |
+#define CONV_VALUE_TO_HEX(v) ((A_UINT8)( ((v & 0x0F) <= 9) ? ((v & 0x0F) + '0') : ((v & 0x0F) - 10 + 'A') ) ) |
+ |
+ |
+enum MinBootFileFormatE |
+{ |
+ MB_FILEFORMAT_RADIOTBL, |
+ MB_FILEFORMAT_PATCH, |
+ MB_FILEFORMAT_COEXCONFIG |
+}; |
+ |
+enum RamPsSection |
+{ |
+ RAM_PS_SECTION, |
+ RAM_PATCH_SECTION, |
+ RAM_DYN_MEM_SECTION |
+}; |
+ |
+enum eType { |
+ eHex, |
+ edecimal |
+}; |
+ |
+ |
+typedef struct tPsTagEntry |
+{ |
+ A_UINT32 TagId; |
+ A_UINT32 TagLen; |
+ A_UINT8 *TagData; |
+} tPsTagEntry, *tpPsTagEntry; |
+ |
+typedef struct tRamPatch |
+{ |
+ A_UINT16 Len; |
+ A_UINT8 * Data; |
+} tRamPatch, *ptRamPatch; |
+ |
+ |
+ |
+typedef struct ST_PS_DATA_FORMAT { |
+ enum eType eDataType; |
+ A_BOOL bIsArray; |
+}ST_PS_DATA_FORMAT; |
+ |
+typedef struct ST_READ_STATUS { |
+ unsigned uTagID; |
+ unsigned uSection; |
+ unsigned uLineCount; |
+ unsigned uCharCount; |
+ unsigned uByteCount; |
+}ST_READ_STATUS; |
+ |
+ |
+/* Stores the number of PS Tags */ |
+static A_UINT32 Tag_Count = 0; |
+ |
+/* Stores the number of patch commands */ |
+static A_UINT32 Patch_Count = 0; |
+static A_UINT32 Total_tag_lenght = 0; |
+static A_BOOL BDADDR = FALSE; |
+A_UINT32 StartTagId; |
+ |
+tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE]; |
+tRamPatch RamPatch[MAX_NUM_PATCH_ENTRY]; |
+ |
+ |
+A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat); |
+char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos); |
+char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos); |
+static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index); |
+ |
+/* Function to reads the next character from the input buffer */ |
+char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos) |
+{ |
+ char Ch; |
+ if(buffer == NULL || *pos >=len ) |
+ { |
+ return '\0'; |
+ } else { |
+ Ch = buffer[*pos]; |
+ (*pos)++; |
+ return Ch; |
+ } |
+} |
+/* PS parser helper function */ |
+unsigned int uGetInputDataFormat(char* pCharLine, ST_PS_DATA_FORMAT *pstFormat) |
+{ |
+ if(pCharLine[0] != '[') { |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = true; |
+ return 0; |
+ } |
+ 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; |
+ return 0; |
+ } |
+ else { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A |
+ return 1; |
+ } |
+ } |
+ if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) { |
+ if(pCharLine[4] == ']') { |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = false; |
+ pCharLine += 5; |
+ return 0; |
+ } |
+ else { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A |
+ return 1; |
+ } |
+ } |
+ else if(pCharLine[3] == ']') { //[H:] |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = true; |
+ pCharLine += 4; |
+ return 0; |
+ } |
+ else { //[H: |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); |
+ return 1; |
+ } |
+ } |
+ else if(pCharLine[2]==']') { //[H] |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = true; |
+ pCharLine += 3; |
+ return 0; |
+ } |
+ else { //[H |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); |
+ return 1; |
+ } |
+ 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; |
+ return 0; |
+ } |
+ else { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 1\n")); //[A:H |
+ return 1; |
+ } |
+ } |
+ else if(pCharLine[3]== ']') { //[A:] |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = true; |
+ pCharLine += 4; |
+ return 0; |
+ } |
+ else { //[A: |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 2\n")); |
+ return 1; |
+ } |
+ } |
+ else if(pCharLine[2]==']') { //[H] |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = true; |
+ pCharLine += 3; |
+ return 0; |
+ } |
+ else { //[H |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 3\n")); |
+ return 1; |
+ } |
+ 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; |
+ return 0; |
+ } |
+ else { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 5\n")); //[A:H |
+ return 1; |
+ } |
+ } |
+ else if(pCharLine[3]== ']') { //[A:] |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = true; |
+ pCharLine += 4; |
+ return 0; |
+ } |
+ else { //[A: |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 6\n")); |
+ return 1; |
+ } |
+ } |
+ else if(pCharLine[2]==']') { //[H] |
+ pstFormat->eDataType = eHex; |
+ pstFormat->bIsArray = true; |
+ pCharLine += 3; |
+ return 0; |
+ } |
+ else { //[H |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 7\n")); |
+ return 1; |
+ } |
+ break; |
+ |
+ default: |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 8\n")); |
+ return 1; |
+ } |
+} |
+ |
+unsigned int uReadDataInSection(char *pCharLine, ST_PS_DATA_FORMAT stPS_DataFormat) |
+{ |
+ char *pTokenPtr = pCharLine; |
+ |
+ if(pTokenPtr[0] == '[') { |
+ while(pTokenPtr[0] != ']' && pTokenPtr[0] != '\0') { |
+ pTokenPtr++; |
+ } |
+ if(pTokenPtr[0] == '\0') { |
+ return (0x0FFF); |
+ } |
+ pTokenPtr++; |
+ |
+ |
+ } |
+ if(stPS_DataFormat.eDataType == eHex) { |
+ if(stPS_DataFormat.bIsArray == true) { |
+ //Not implemented |
+ return (0x0FFF); |
+ } |
+ else { |
+ return (A_STRTOL(pTokenPtr, NULL, 16)); |
+ } |
+ } |
+ else { |
+ //Not implemented |
+ return (0x0FFF); |
+ } |
+} |
+A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat) |
+{ |
+ char *Buffer; |
+ char *pCharLine; |
+ A_UINT8 TagCount; |
+ A_UINT16 ByteCount; |
+ A_UINT8 ParseSection=RAM_PS_SECTION; |
+ A_UINT32 pos; |
+ |
+ |
+ |
+ int uReadCount; |
+ ST_PS_DATA_FORMAT stPS_DataFormat; |
+ ST_READ_STATUS stReadStatus = {0, 0, 0,0}; |
+ pos = 0; |
+ Buffer = NULL; |
+ |
+ if (srcbuffer == NULL || srclen == 0) |
+ { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Could not open .\n")); |
+ return A_ERROR; |
+ } |
+ TagCount = 0; |
+ ByteCount = 0; |
+ Buffer = A_MALLOC(LINE_SIZE_MAX + 1); |
+ if(NULL == Buffer) { |
+ return A_ERROR; |
+ } |
+ if (FileFormat == MB_FILEFORMAT_PATCH) |
+ { |
+ int LineRead = 0; |
+ while((pCharLine = AthGetLine(Buffer, LINE_SIZE_MAX, srcbuffer,srclen,&pos)) != NULL) |
+ { |
+ |
+ SKIP_BLANKS(pCharLine); |
+ |
+ // Comment line or empty line |
+ if ((pCharLine[0] == '/') && (pCharLine[1] == '/')) |
+ { |
+ continue; |
+ } |
+ |
+ if ((pCharLine[0] == '#')) { |
+ if (stReadStatus.uSection != 0) |
+ { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("error\n")); |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ } |
+ else { |
+ stReadStatus.uSection = 1; |
+ continue; |
+ } |
+ } |
+ if ((pCharLine[0] == '/') && (pCharLine[1] == '*')) |
+ { |
+ pCharLine+=2; |
+ SKIP_BLANKS(pCharLine); |
+ |
+ if(!strncmp(pCharLine,"PA",2)||!strncmp(pCharLine,"Pa",2)||!strncmp(pCharLine,"pa",2)) |
+ ParseSection=RAM_PATCH_SECTION; |
+ |
+ if(!strncmp(pCharLine,"DY",2)||!strncmp(pCharLine,"Dy",2)||!strncmp(pCharLine,"dy",2)) |
+ ParseSection=RAM_DYN_MEM_SECTION; |
+ |
+ if(!strncmp(pCharLine,"PS",2)||!strncmp(pCharLine,"Ps",2)||!strncmp(pCharLine,"ps",2)) |
+ ParseSection=RAM_PS_SECTION; |
+ |
+ LineRead = 0; |
+ stReadStatus.uSection = 0; |
+ |
+ continue; |
+ } |
+ |
+ switch(ParseSection) |
+ { |
+ case RAM_PS_SECTION: |
+ { |
+ if (stReadStatus.uSection == 1) //TagID |
+ { |
+ SKIP_BLANKS(pCharLine); |
+ if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail\n")); |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ } |
+ //pCharLine +=5; |
+ PsTagEntry[TagCount].TagId = uReadDataInSection(pCharLine, stPS_DataFormat); |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG ID %d \n",PsTagEntry[TagCount].TagId)); |
+ |
+ //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag # %x\n", PsTagEntry[TagCount].TagId); |
+ if (TagCount == 0) |
+ { |
+ StartTagId = PsTagEntry[TagCount].TagId; |
+ } |
+ stReadStatus.uSection = 2; |
+ } |
+ else if (stReadStatus.uSection == 2) //TagLength |
+ { |
+ |
+ if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail \n")); |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ } |
+ //pCharLine +=5; |
+ ByteCount = uReadDataInSection(pCharLine, stPS_DataFormat); |
+ |
+ //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag length %x\n", ByteCount)); |
+ if (ByteCount > LINE_SIZE_MAX/2) |
+ { |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ } |
+ PsTagEntry[TagCount].TagLen = ByteCount; |
+ PsTagEntry[TagCount].TagData = (A_UINT8*)A_MALLOC(ByteCount); |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG Length %d Tag Index %d \n",PsTagEntry[TagCount].TagLen,TagCount)); |
+ stReadStatus.uSection = 3; |
+ stReadStatus.uLineCount = 0; |
+ } |
+ else if( stReadStatus.uSection == 3) { //Data |
+ |
+ if(stReadStatus.uLineCount == 0) { |
+ if(uGetInputDataFormat(pCharLine,&stPS_DataFormat)) { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat Fail\n")); |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ } |
+ //pCharLine +=5; |
+ } |
+ SKIP_BLANKS(pCharLine); |
+ stReadStatus.uCharCount = 0; |
+ if(pCharLine[stReadStatus.uCharCount] == '[') { |
+ while(pCharLine[stReadStatus.uCharCount] != ']' && pCharLine[stReadStatus.uCharCount] != '\0' ) { |
+ stReadStatus.uCharCount++; |
+ } |
+ if(pCharLine[stReadStatus.uCharCount] == ']' ) { |
+ stReadStatus.uCharCount++; |
+ } else { |
+ stReadStatus.uCharCount = 0; |
+ } |
+ } |
+ uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount; |
+ //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ")); |
+ if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) { |
+ while(uReadCount > 0) { |
+ PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] = |
+ (A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[stReadStatus.uCharCount]) << 4) |
+ | (A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[stReadStatus.uCharCount + 1])); |
+ |
+ PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] = |
+ (A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[stReadStatus.uCharCount + 3]) << 4) |
+ | (A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[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 |
+ } |
+ |
+ 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)&&(++TagCount == RAMPS_MAX_PS_TAGS_PER_FILE)) |
+ { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n Buffer over flow PS File too big!!!")); |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ //Sleep (3000); |
+ //exit(1); |
+ } |
+ |
+ } |
+ } |
+ |
+ break; |
+ default: |
+ { |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ } |
+ break; |
+ } |
+ LineRead++; |
+ } |
+ Tag_Count = TagCount; |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Number of Tags %d\n", Tag_Count)); |
+ } |
+ |
+ |
+ if (TagCount > RAMPS_MAX_PS_TAGS_PER_FILE) |
+ { |
+ |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_ERROR; |
+ } |
+ |
+ if(Buffer != NULL) { |
+ A_FREE(Buffer); |
+ } |
+ return A_OK; |
+ |
+} |
+ |
+ |
+ |
+/********************/ |
+ |
+ |
+A_STATUS GetNextTwoChar(A_UCHAR *srcbuffer,A_UINT32 len, A_UINT32 *pos, char * buffer) |
+{ |
+ unsigned char ch; |
+ |
+ ch = AthReadChar(srcbuffer,len,pos); |
+ if(ch != '\0' && IS_HEX(ch)) { |
+ buffer[0] = ch; |
+ } else |
+ { |
+ return A_ERROR; |
+ } |
+ ch = AthReadChar(srcbuffer,len,pos); |
+ if(ch != '\0' && IS_HEX(ch)) { |
+ buffer[1] = ch; |
+ } else |
+ { |
+ return A_ERROR; |
+ } |
+ return A_OK; |
+} |
+ |
+A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen) |
+{ |
+ |
+ char Byte[3]; |
+ char Line[MAX_BYTE_LENGTH + 1]; |
+ int ByteCount,ByteCount_Org; |
+ int count; |
+ int i,j,k; |
+ int data; |
+ A_UINT32 filepos; |
+ Byte[2] = '\0'; |
+ j = 0; |
+ filepos = 0; |
+ |
+ while(NULL != AthGetLine(Line,MAX_BYTE_LENGTH,patchbuffer,patchlen,&filepos)) { |
+ if(strlen(Line) <= 1 || !IS_HEX(Line[0])) { |
+ continue; |
+ } else { |
+ break; |
+ } |
+ } |
+ ByteCount = A_STRTOL(Line, NULL, 16); |
+ ByteCount_Org = ByteCount; |
+ |
+ while(ByteCount > MAX_BYTE_LENGTH){ |
+ |
+ /* Handle case when the number of patch buffer is more than the 20K */ |
+ if(MAX_NUM_PATCH_ENTRY == Patch_Count) { |
+ for(i = 0; i < Patch_Count; i++) { |
+ A_FREE(RamPatch[i].Data); |
+ } |
+ return A_ERROR; |
+ } |
+ RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH; |
+ RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(MAX_BYTE_LENGTH); |
+ Patch_Count ++; |
+ |
+ |
+ ByteCount= ByteCount - MAX_BYTE_LENGTH; |
+ } |
+ |
+ RamPatch[Patch_Count].Len= (ByteCount & 0xFF); |
+ if(ByteCount != 0) { |
+ RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(ByteCount); |
+ Patch_Count ++; |
+ } |
+ count = 0; |
+ while(ByteCount_Org > MAX_BYTE_LENGTH){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j)); |
+ for (i = 0,k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++,count +=2) { |
+ if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) { |
+ return A_ERROR; |
+ } |
+ data = A_STRTOUL(&Byte[0], NULL, 16); |
+ RamPatch[j].Data[k] = (data & 0xFF); |
+ |
+ |
+ } |
+ j++; |
+ ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH; |
+ } |
+ if(j == 0){ |
+ j++; |
+ } |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j)); |
+ for (k=0; k < ByteCount_Org; i += 2,k++,count+=2) { |
+ if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) { |
+ return A_ERROR; |
+ } |
+ data = A_STRTOUL(Byte, NULL, 16); |
+ RamPatch[j].Data[k] = (data & 0xFF); |
+ |
+ |
+ } |
+ return A_OK; |
+} |
+ |
+ |
+/********************/ |
+A_STATUS AthDoParsePS(A_UCHAR *srcbuffer, A_UINT32 srclen) |
+{ |
+ A_STATUS status; |
+ int i; |
+ A_BOOL BDADDR_Present = A_ERROR; |
+ |
+ |
+ |
+ status = A_ERROR; |
+ |
+ if(NULL != srcbuffer && srclen != 0) |
+ { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("File Open Operation Successful\n")); |
+ |
+ status = AthParseFilesUnified(srcbuffer,srclen,MB_FILEFORMAT_PATCH); |
+ } |
+ |
+ |
+ |
+ if(Tag_Count == 0){ |
+ Total_tag_lenght = 10; |
+ |
+ } |
+ else{ |
+ for(i=0; i<Tag_Count; i++){ |
+ if(PsTagEntry[i].TagId == 1){ |
+ BDADDR_Present = A_OK; |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("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){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("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); |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Total Length %d\n",Total_tag_lenght)); |
+ |
+ |
+ return status; |
+} |
+char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos) |
+{ |
+ |
+ int count; |
+ static short flag; |
+ char CharRead; |
+ count = 0; |
+ flag = A_ERROR; |
+ |
+ do |
+ { |
+ CharRead = AthReadChar(srcbuffer,len,pos); |
+ if( CharRead == '\0' ) { |
+ buffer[count+1] = '\0'; |
+ if(count == 0) { |
+ return NULL; |
+ } |
+ else { |
+ return buffer; |
+ } |
+ } |
+ |
+ if(CharRead == 13) { |
+ } else if(CharRead == 10) { |
+ buffer[count] ='\0'; |
+ flag = A_ERROR; |
+ return buffer; |
+ }else { |
+ buffer[count++] = CharRead; |
+ } |
+ |
+ } |
+ while(count < maxlen-1 && CharRead != '\0'); |
+ buffer[count] = '\0'; |
+ |
+ return buffer; |
+} |
+ |
+static void LoadHeader(A_UCHAR *HCI_PS_Command,A_UCHAR opcode,int length,int index){ |
+ |
+ HCI_PS_Command[0]= 0x0B; |
+ HCI_PS_Command[1]= 0xFC; |
+ HCI_PS_Command[2]= length + 4; |
+ HCI_PS_Command[3]= opcode; |
+ HCI_PS_Command[4]= (index & 0xFF); |
+ HCI_PS_Command[5]= ((index>>8) & 0xFF); |
+ HCI_PS_Command[6]= length; |
+} |
+ |
+///////////////////////// |
+// |
+int AthCreateCommandList(PSCmdPacket **HciPacketList, A_UINT32 *numPackets) |
+{ |
+ |
+ A_UINT8 count; |
+ A_UINT32 NumcmdEntry = 0; |
+ |
+ A_UINT32 Crc = 0; |
+ *numPackets = 0; |
+ |
+ |
+ if(Patch_Count > 0) |
+ Crc |= RAM_PATCH_REGION; |
+ if(Tag_Count > 0) |
+ Crc |= RAM_PS_REGION; |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("PS Thread Started CRC %x Patch Count %d Tag Count %d \n",Crc,Patch_Count,Tag_Count)); |
+ |
+ if(Patch_Count || Tag_Count ){ |
+ NumcmdEntry+=(2 + Patch_Count + Tag_Count); /* CRC Packet + PS Reset Packet + Patch List + PS List*/ |
+ if(Patch_Count > 0) { |
+ NumcmdEntry++; /* Patch Enable Command */ |
+ } |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size %d \r\n",NumcmdEntry,sizeof(PSCmdPacket) * NumcmdEntry)); |
+ (*HciPacketList) = A_MALLOC(sizeof(PSCmdPacket) * NumcmdEntry); |
+ if(NULL == *HciPacketList) { |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed \r\n")); |
+ } |
+ AthPSCreateHCICommand(PS_VERIFY_CRC,Crc,*HciPacketList,numPackets); |
+ if(Patch_Count > 0){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Write Patch**** \r\n")); |
+ AthPSCreateHCICommand(WRITE_PATCH,Patch_Count,*HciPacketList,numPackets); |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Enable Patch**** \r\n")); |
+ AthPSCreateHCICommand(ENABLE_PATCH,0,*HciPacketList,numPackets); |
+ } |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Reset**** \r\n")); |
+ AthPSCreateHCICommand(PS_RESET,Total_tag_lenght,*HciPacketList,numPackets); |
+ if(Tag_Count > 0){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Write**** \r\n")); |
+ AthPSCreateHCICommand(PS_WRITE,Tag_Count,*HciPacketList,numPackets); |
+ } |
+ } |
+ if(!BDADDR){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR not present \r\n")); |
+ |
+ } |
+ for(count = 0; count < Patch_Count; count++) { |
+ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing Patch Buffer %d \r\n",count)); |
+ A_FREE(RamPatch[Patch_Count].Data); |
+ } |
+ |
+ for(count = 0; count < Tag_Count; count++) { |
+ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing PS Buffer %d \r\n",count)); |
+ A_FREE(PsTagEntry[count].TagData); |
+ } |
+ |
+/* |
+ * SDIO Transport uses synchronous mode of data transfer |
+ * So, AthPSOperations() call returns only after receiving the |
+ * command complete event. |
+ */ |
+ return *numPackets; |
+} |
+ |
+ |
+//////////////////////// |
+ |
+///////////// |
+static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index) |
+{ |
+ A_UCHAR *HCI_PS_Command; |
+ A_UINT32 Length; |
+ int i,j; |
+ |
+ switch(Opcode) |
+ { |
+ case WRITE_PATCH: |
+ |
+ |
+ for(i=0;i< Param1;i++){ |
+ |
+ HCI_PS_Command = (A_UCHAR *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER); |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Allocated Buffer Size %d\n",RamPatch[i].Len+HCI_COMMAND_HEADER)); |
+ if(HCI_PS_Command == NULL){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); |
+ return A_ERROR; |
+ } |
+ memset (HCI_PS_Command, 0, RamPatch[i].Len+HCI_COMMAND_HEADER); |
+ LoadHeader(HCI_PS_Command,Opcode,RamPatch[i].Len,i); |
+ for(j=0;j<RamPatch[i].Len;j++){ |
+ HCI_PS_Command[HCI_COMMAND_HEADER+j]=RamPatch[i].Data[j]; |
+ } |
+ PSPatchPacket[*index].Hcipacket = HCI_PS_Command; |
+ PSPatchPacket[*index].packetLen = RamPatch[i].Len+HCI_COMMAND_HEADER; |
+ (*index)++; |
+ |
+ |
+ } |
+ |
+ break; |
+ |
+ case ENABLE_PATCH: |
+ |
+ |
+ Length = 0; |
+ i= 0; |
+ HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER); |
+ if(HCI_PS_Command == NULL){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); |
+ return A_ERROR; |
+ } |
+ |
+ memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER); |
+ LoadHeader(HCI_PS_Command,Opcode,Length,i); |
+ PSPatchPacket[*index].Hcipacket = HCI_PS_Command; |
+ PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER; |
+ (*index)++; |
+ |
+ break; |
+ |
+ case PS_RESET: |
+ Length = 0x06; |
+ i=0; |
+ HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER); |
+ if(HCI_PS_Command == NULL){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); |
+ return A_ERROR; |
+ } |
+ memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER); |
+ LoadHeader(HCI_PS_Command,Opcode,Length,i); |
+ HCI_PS_Command[7]= 0x00; |
+ HCI_PS_Command[Length+HCI_COMMAND_HEADER -2]= (Param1 & 0xFF); |
+ HCI_PS_Command[Length+HCI_COMMAND_HEADER -1]= ((Param1 >> 8) & 0xFF); |
+ PSPatchPacket[*index].Hcipacket = HCI_PS_Command; |
+ PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER; |
+ (*index)++; |
+ |
+ break; |
+ |
+ case PS_WRITE: |
+ for(i=0;i< Param1;i++){ |
+ if(PsTagEntry[i].TagId ==1) |
+ BDADDR = TRUE; |
+ |
+ HCI_PS_Command = (A_UCHAR *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER); |
+ if(HCI_PS_Command == NULL){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); |
+ return A_ERROR; |
+ } |
+ |
+ memset (HCI_PS_Command, 0, PsTagEntry[i].TagLen+HCI_COMMAND_HEADER); |
+ LoadHeader(HCI_PS_Command,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId); |
+ |
+ for(j=0;j<PsTagEntry[i].TagLen;j++){ |
+ HCI_PS_Command[HCI_COMMAND_HEADER+j]=PsTagEntry[i].TagData[j]; |
+ } |
+ |
+ PSPatchPacket[*index].Hcipacket = HCI_PS_Command; |
+ PSPatchPacket[*index].packetLen = PsTagEntry[i].TagLen+HCI_COMMAND_HEADER; |
+ (*index)++; |
+ |
+ } |
+ |
+ break; |
+ |
+ |
+ case PS_VERIFY_CRC: |
+ Length = 0x0; |
+ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("VALUE of CRC:%d At index %d\r\n",Param1,*index)); |
+ |
+ HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER); |
+ if(HCI_PS_Command == NULL){ |
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n")); |
+ return A_ERROR; |
+ } |
+ memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER); |
+ LoadHeader(HCI_PS_Command,Opcode,Length,Param1); |
+ |
+ PSPatchPacket[*index].Hcipacket = HCI_PS_Command; |
+ PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER; |
+ (*index)++; |
+ |
+ break; |
+ |
+ case CHANGE_BDADDR: |
+ break; |
+ } |
+ return A_OK; |
+} |
+A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets) |
+{ |
+ int i; |
+ if(*HciPacketList == NULL) { |
+ return A_ERROR; |
+ } |
+ for(i = 0; i < numPackets;i++) { |
+ A_FREE((*HciPacketList)[i].Hcipacket); |
+ } |
+ A_FREE(*HciPacketList); |
+ return A_OK; |
+} |