Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.git] / drivers / staging / ath6kl / miscdrv / ar3kps / ar3kpsparser.c
1 /*
2  * Copyright (c) 2004-2010 Atheros Communications Inc.
3  * All rights reserved.
4  *
5  * This file implements the Atheros PS and patch parser.
6  * It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands.
7  *
8  *
9  *
10  * ar3kpsparser.c
11  *
12  *
13  *
14  * The software source and binaries included in this development package are
15  * licensed, not sold. You, or your company, received the package under one
16  * or more license agreements. The rights granted to you are specifically
17  * listed in these license agreement(s). All other rights remain with Atheros
18  * Communications, Inc., its subsidiaries, or the respective owner including
19  * those listed on the included copyright notices..  Distribution of any
20  * portion of this package must be in strict compliance with the license
21  * agreement(s) terms.
22  *
23  *
24  *
25  */
26
27
28 #include "ar3kpsparser.h"
29
30 #include <linux/ctype.h>
31 #include <linux/kernel.h>
32
33 #define BD_ADDR_SIZE            6
34 #define WRITE_PATCH             8
35 #define ENABLE_PATCH            11
36 #define PS_RESET                2
37 #define PS_WRITE                1
38 #define PS_VERIFY_CRC           9
39 #define CHANGE_BDADDR           15
40
41 #define HCI_COMMAND_HEADER      7
42
43 #define HCI_EVENT_SIZE          7
44
45 #define WRITE_PATCH_COMMAND_STATUS_OFFSET 5
46
47 #define PS_RAM_SIZE     2048
48
49 #define RAM_PS_REGION           (1<<0)
50 #define RAM_PATCH_REGION        (1<<1)
51 #define RAMPS_MAX_PS_DATA_PER_TAG         20000
52 #define MAX_RADIO_CFG_TABLE_SIZE  244
53 #define RAMPS_MAX_PS_TAGS_PER_FILE        50
54
55 #define PS_MAX_LEN                        500 
56 #define LINE_SIZE_MAX                     (PS_MAX_LEN *2) 
57
58 /* Constant values used by parser */
59 #define BYTES_OF_PS_DATA_PER_LINE         16
60 #define RAMPS_MAX_PS_DATA_PER_TAG         20000
61
62
63 /* Number pf PS/Patch entries in an HCI packet */
64 #define MAX_BYTE_LENGTH                   244
65
66 #define SKIP_BLANKS(str) while (*str == ' ') str++
67
68 enum MinBootFileFormatE
69 {
70    MB_FILEFORMAT_RADIOTBL,
71    MB_FILEFORMAT_PATCH,
72    MB_FILEFORMAT_COEXCONFIG
73 };
74
75 enum RamPsSection
76 {
77    RAM_PS_SECTION,
78    RAM_PATCH_SECTION,
79    RAM_DYN_MEM_SECTION
80 };
81
82 enum eType {
83    eHex,
84    edecimal
85 };
86
87
88 typedef struct tPsTagEntry
89 {
90    A_UINT32   TagId;
91    A_UINT32   TagLen;
92    A_UINT8    *TagData;
93 } tPsTagEntry, *tpPsTagEntry;
94
95 typedef struct tRamPatch
96 {
97    A_UINT16   Len;
98    A_UINT8    * Data;
99 } tRamPatch, *ptRamPatch;
100
101
102
103 typedef struct ST_PS_DATA_FORMAT {
104    enum eType   eDataType;
105    A_BOOL    bIsArray;
106 }ST_PS_DATA_FORMAT;
107
108 typedef struct ST_READ_STATUS {
109     unsigned uTagID;
110     unsigned uSection;
111     unsigned uLineCount;
112     unsigned uCharCount;
113     unsigned uByteCount;
114 }ST_READ_STATUS;
115
116
117 /* Stores the number of PS Tags */
118 static A_UINT32 Tag_Count = 0;
119
120 /* Stores the number of patch commands */
121 static A_UINT32 Patch_Count = 0;
122 static A_UINT32 Total_tag_lenght = 0;
123 A_BOOL BDADDR = FALSE;
124 A_UINT32      StartTagId;
125
126 tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE];
127 tRamPatch   RamPatch[MAX_NUM_PATCH_ENTRY];
128
129
130 A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat);
131 char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos);
132 char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos);
133 static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index);
134
135 /* Function to reads the next character from the input buffer */
136 char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos) 
137 {
138     char Ch;
139     if(buffer == NULL || *pos >=len )
140     {
141         return '\0';
142     } else {
143         Ch = buffer[*pos];
144         (*pos)++;
145         return Ch;
146     }
147 }
148 /* PS parser helper function */
149 unsigned int uGetInputDataFormat(char* pCharLine, ST_PS_DATA_FORMAT *pstFormat) 
150 {
151     if(pCharLine[0] != '[') {
152         pstFormat->eDataType = eHex;
153         pstFormat->bIsArray = true;
154         return 0;
155     }
156     switch(pCharLine[1]) {
157         case 'H':
158         case 'h':
159         if(pCharLine[2]==':') {
160             if((pCharLine[3]== 'a') || (pCharLine[3]== 'A')) {
161                 if(pCharLine[4] == ']') {
162                     pstFormat->eDataType = eHex;
163                     pstFormat->bIsArray = true;
164                     pCharLine += 5;
165                     return 0;
166                 }
167                 else {
168                        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A
169                     return 1;
170                 }
171             }
172             if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) {
173                 if(pCharLine[4] == ']') {
174                     pstFormat->eDataType = eHex;
175                     pstFormat->bIsArray = false;
176                     pCharLine += 5;
177                     return 0;
178                 }
179                 else {
180                        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A
181                     return 1;
182                 }
183             }
184             else if(pCharLine[3] == ']') {         //[H:]
185                 pstFormat->eDataType = eHex;
186                 pstFormat->bIsArray = true;
187                 pCharLine += 4;
188                 return 0;
189             }
190             else {                            //[H:
191                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n"));
192                 return 1;                    
193             }
194         }
195         else if(pCharLine[2]==']') {    //[H]
196             pstFormat->eDataType = eHex;
197             pstFormat->bIsArray = true;
198             pCharLine += 3;
199             return 0;
200         }
201         else {                      //[H
202             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n"));
203             return 1;            
204         }
205         break;
206
207         case 'A':
208         case 'a':
209         if(pCharLine[2]==':') {
210             if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
211                 if(pCharLine[4] == ']') {
212                     pstFormat->eDataType = eHex;
213                     pstFormat->bIsArray = true;
214                     pCharLine += 5;
215                     return 0;
216                 }
217                 else {
218                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 1\n")); //[A:H
219                     return 1;
220                 }
221              }
222             else if(pCharLine[3]== ']') {         //[A:]
223                 pstFormat->eDataType = eHex;
224                 pstFormat->bIsArray = true;
225                 pCharLine += 4;
226                 return 0;
227             }
228             else {                            //[A:
229                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 2\n"));
230                 return 1;                    
231             }
232         }
233         else if(pCharLine[2]==']') {    //[H]
234             pstFormat->eDataType = eHex;
235             pstFormat->bIsArray = true;
236             pCharLine += 3;
237             return 0;
238         }
239         else {                      //[H
240             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 3\n"));
241             return 1;            
242         }
243         break;
244
245         case 'S':
246         case 's':
247         if(pCharLine[2]==':') {
248             if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
249                 if(pCharLine[4] == ']') {
250                     pstFormat->eDataType = eHex;
251                     pstFormat->bIsArray = true;
252                     pCharLine += 5;
253                     return 0;
254                 }
255                 else {
256                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 5\n")); //[A:H
257                     return 1;
258                 }
259              }
260             else if(pCharLine[3]== ']') {         //[A:]
261                 pstFormat->eDataType = eHex;
262                 pstFormat->bIsArray = true;
263                 pCharLine += 4;
264                 return 0;
265             }
266             else {                            //[A:
267                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 6\n"));
268                 return 1;                    
269             }
270         }
271         else if(pCharLine[2]==']') {    //[H]
272             pstFormat->eDataType = eHex;
273             pstFormat->bIsArray = true;
274             pCharLine += 3;
275             return 0;
276         }
277         else {                      //[H
278             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 7\n"));
279             return 1;            
280         }
281         break;
282     
283         default:
284         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 8\n"));
285         return 1;
286     }
287 }
288
289 unsigned int uReadDataInSection(char *pCharLine, ST_PS_DATA_FORMAT stPS_DataFormat)
290 {
291     char *pTokenPtr = pCharLine;
292
293     if(pTokenPtr[0] == '[') {
294         while(pTokenPtr[0] != ']' && pTokenPtr[0] != '\0') {
295             pTokenPtr++;
296         }
297         if(pTokenPtr[0] == '\0') {
298             return (0x0FFF);
299         }
300         pTokenPtr++;
301             
302
303     }
304     if(stPS_DataFormat.eDataType == eHex) {
305         if(stPS_DataFormat.bIsArray == true) {
306             //Not implemented
307             return (0x0FFF);
308         }
309         else {
310             return (A_STRTOL(pTokenPtr, NULL, 16));
311         }
312     }
313     else {
314         //Not implemented
315         return (0x0FFF);
316     }
317 }
318 A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat)
319 {
320    char     *Buffer;
321    char     *pCharLine;
322    A_UINT8    TagCount;
323    A_UINT16   ByteCount;
324    A_UINT8    ParseSection=RAM_PS_SECTION;
325    A_UINT32 pos;
326
327
328
329    int uReadCount;
330    ST_PS_DATA_FORMAT stPS_DataFormat;
331    ST_READ_STATUS   stReadStatus = {0, 0, 0,0};
332    pos = 0;
333    Buffer = NULL;
334
335    if (srcbuffer == NULL || srclen == 0)
336    {
337       AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Could not open .\n"));
338       return A_ERROR;
339    }
340    TagCount = 0;
341    ByteCount = 0;
342    Buffer = A_MALLOC(LINE_SIZE_MAX + 1);
343    if(NULL == Buffer) {
344        return A_ERROR;
345    }
346    if (FileFormat == MB_FILEFORMAT_PATCH)
347    {
348       int LineRead = 0;
349       while((pCharLine = AthGetLine(Buffer, LINE_SIZE_MAX, srcbuffer,srclen,&pos)) != NULL)
350       {
351
352          SKIP_BLANKS(pCharLine);
353
354          // Comment line or empty line
355          if ((pCharLine[0] == '/') && (pCharLine[1] == '/'))
356          {
357             continue;
358          }
359          
360          if ((pCharLine[0] == '#')) { 
361              if (stReadStatus.uSection != 0)
362              {
363                  AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("error\n"));
364                  if(Buffer != NULL) {
365                      A_FREE(Buffer);
366                  }
367                  return A_ERROR;
368              }
369              else {
370                  stReadStatus.uSection = 1;
371                  continue;
372              }
373          }
374          if ((pCharLine[0] == '/') && (pCharLine[1] == '*'))
375          {
376             pCharLine+=2;
377             SKIP_BLANKS(pCharLine);
378
379             if(!strncmp(pCharLine,"PA",2)||!strncmp(pCharLine,"Pa",2)||!strncmp(pCharLine,"pa",2))
380                 ParseSection=RAM_PATCH_SECTION;
381
382             if(!strncmp(pCharLine,"DY",2)||!strncmp(pCharLine,"Dy",2)||!strncmp(pCharLine,"dy",2))
383                 ParseSection=RAM_DYN_MEM_SECTION;
384
385             if(!strncmp(pCharLine,"PS",2)||!strncmp(pCharLine,"Ps",2)||!strncmp(pCharLine,"ps",2))
386                 ParseSection=RAM_PS_SECTION;
387
388             LineRead = 0;
389             stReadStatus.uSection = 0;
390
391             continue;
392     }
393          
394          switch(ParseSection)
395          {
396              case RAM_PS_SECTION:
397              {
398                  if (stReadStatus.uSection == 1)  //TagID
399                  {
400                     SKIP_BLANKS(pCharLine);
401                     if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) {
402                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail\n"));
403                      if(Buffer != NULL) {
404                              A_FREE(Buffer);
405                      }
406                         return A_ERROR;
407                     }    
408                     //pCharLine +=5;
409                     PsTagEntry[TagCount].TagId = uReadDataInSection(pCharLine, stPS_DataFormat);                            
410                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG ID %d \n",PsTagEntry[TagCount].TagId));
411
412                     //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag # %x\n", PsTagEntry[TagCount].TagId);
413                     if (TagCount == 0)
414                     {
415                        StartTagId = PsTagEntry[TagCount].TagId;
416                     }
417                     stReadStatus.uSection = 2;
418                  }
419                  else if (stReadStatus.uSection == 2) //TagLength
420                  {
421             
422                     if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) {
423                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail \n"));
424                      if(Buffer != NULL) {
425                              A_FREE(Buffer);
426                      }
427                         return A_ERROR;
428                     }
429                     //pCharLine +=5;
430                     ByteCount = uReadDataInSection(pCharLine, stPS_DataFormat);
431
432                     //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag length %x\n", ByteCount));
433                     if (ByteCount > LINE_SIZE_MAX/2)
434                     {
435                      if(Buffer != NULL) {
436                              A_FREE(Buffer);
437                      }
438                        return A_ERROR;
439                     }
440                     PsTagEntry[TagCount].TagLen = ByteCount;
441                     PsTagEntry[TagCount].TagData = (A_UINT8*)A_MALLOC(ByteCount);
442                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG Length %d  Tag Index %d \n",PsTagEntry[TagCount].TagLen,TagCount));
443                     stReadStatus.uSection = 3;
444                     stReadStatus.uLineCount = 0;
445                  }
446                  else if( stReadStatus.uSection == 3) {  //Data
447
448                     if(stReadStatus.uLineCount == 0) {
449                         if(uGetInputDataFormat(pCharLine,&stPS_DataFormat)) {
450                             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat Fail\n"));
451                             if(Buffer != NULL) {
452                                  A_FREE(Buffer);
453                          }
454                             return A_ERROR;
455                         }
456                         //pCharLine +=5;
457                     }
458            SKIP_BLANKS(pCharLine);
459                     stReadStatus.uCharCount = 0;
460             if(pCharLine[stReadStatus.uCharCount] == '[') {
461             while(pCharLine[stReadStatus.uCharCount] != ']' && pCharLine[stReadStatus.uCharCount] != '\0' ) {
462                             stReadStatus.uCharCount++;
463             }
464             if(pCharLine[stReadStatus.uCharCount] == ']' ) {
465                             stReadStatus.uCharCount++;
466             } else {
467                             stReadStatus.uCharCount = 0;
468             }
469             }
470                     uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount;
471                     //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" "));
472                     if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) {
473                        while(uReadCount > 0) {
474                            PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] =
475                                                      (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4)
476                                                      | (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1]));
477
478                            PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] =
479                                                      (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4)
480                                                      | (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4]));
481
482                            stReadStatus.uCharCount += 6; // read two bytes, plus a space;
483                            stReadStatus.uByteCount += 2;
484                            uReadCount -= 2;
485                        }
486                        if(ByteCount > BYTES_OF_PS_DATA_PER_LINE) {
487                               ByteCount -= BYTES_OF_PS_DATA_PER_LINE;
488                        }
489                        else {
490                           ByteCount = 0;
491                        }
492                     }
493                     else {
494                         //to be implemented
495                     }
496
497                     stReadStatus.uLineCount++;
498                     
499                     if(ByteCount == 0) {
500                         stReadStatus.uSection = 0;
501                         stReadStatus.uCharCount = 0;
502                         stReadStatus.uLineCount = 0;
503                         stReadStatus.uByteCount = 0;
504                     }
505                     else { 
506                         stReadStatus.uCharCount = 0;
507                     }
508
509                     if((stReadStatus.uSection == 0)&&(++TagCount == RAMPS_MAX_PS_TAGS_PER_FILE))
510                     {
511                        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n Buffer over flow PS File too big!!!"));
512                        if(Buffer != NULL) {
513                            A_FREE(Buffer);
514                        }
515                        return A_ERROR;
516                        //Sleep (3000);
517                        //exit(1);
518                     }
519         
520                  }
521              }
522
523              break;
524              default:
525              {
526                    if(Buffer != NULL) {
527                        A_FREE(Buffer);
528                    }
529                    return A_ERROR;
530              }
531              break;
532          }
533          LineRead++;
534       }
535       Tag_Count = TagCount;
536       AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Number of Tags %d\n", Tag_Count));
537    }
538
539
540    if (TagCount > RAMPS_MAX_PS_TAGS_PER_FILE)
541    {
542
543       if(Buffer != NULL) {
544            A_FREE(Buffer);
545       }
546       return A_ERROR;
547    }
548
549    if(Buffer != NULL) {
550         A_FREE(Buffer);
551    }
552    return A_OK;
553
554 }
555
556
557
558 /********************/
559
560
561 A_STATUS GetNextTwoChar(A_UCHAR *srcbuffer,A_UINT32 len, A_UINT32 *pos, char * buffer)
562 {
563     unsigned char ch;
564
565     ch = AthReadChar(srcbuffer,len,pos);
566     if(ch != '\0' && isxdigit(ch)) {
567         buffer[0] =  ch;
568     } else 
569     {
570         return A_ERROR;
571     }
572     ch = AthReadChar(srcbuffer,len,pos);
573     if(ch != '\0' && isxdigit(ch)) {
574         buffer[1] =  ch;
575     } else 
576     {
577         return A_ERROR;
578     }
579     return A_OK;
580 }
581
582 A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen)
583 {
584
585     char  Byte[3];
586     char   Line[MAX_BYTE_LENGTH + 1];
587     int    ByteCount,ByteCount_Org;
588     int count;
589     int i,j,k;
590     int data;
591     A_UINT32 filepos;
592     Byte[2] = '\0';
593     j = 0;
594     filepos = 0;
595     Patch_Count = 0;
596
597     while(NULL != AthGetLine(Line,MAX_BYTE_LENGTH,patchbuffer,patchlen,&filepos)) {
598         if(strlen(Line) <= 1 || !isxdigit(Line[0])) {
599             continue;
600         } else {
601             break;
602         }
603     }
604     ByteCount = A_STRTOL(Line, NULL, 16);
605     ByteCount_Org = ByteCount;
606
607     while(ByteCount > MAX_BYTE_LENGTH){
608
609         /* Handle case when the number of patch buffer is more than the 20K */
610         if(MAX_NUM_PATCH_ENTRY == Patch_Count) {
611             for(i = 0; i < Patch_Count; i++) {
612                 A_FREE(RamPatch[i].Data);
613             }
614             return A_ERROR;
615         }
616         RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH;
617         RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(MAX_BYTE_LENGTH);
618         Patch_Count ++;
619
620
621         ByteCount= ByteCount - MAX_BYTE_LENGTH;
622     }
623
624     RamPatch[Patch_Count].Len= (ByteCount & 0xFF);
625     if(ByteCount != 0) {
626         RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(ByteCount);
627         Patch_Count ++;
628     }
629     count = 0;
630     while(ByteCount_Org > MAX_BYTE_LENGTH){
631         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j));
632         for (i = 0,k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++,count +=2) {
633             if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) {
634                 return A_ERROR;
635             }
636             data = A_STRTOUL(&Byte[0], NULL, 16);
637             RamPatch[j].Data[k] = (data & 0xFF);
638
639
640         }
641         j++;
642         ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH;
643     }
644     if(j == 0){
645         j++;
646     }
647     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j));
648     for (k=0; k < ByteCount_Org; i += 2,k++,count+=2) {
649         if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) {
650             return A_ERROR;
651         }
652         data = A_STRTOUL(Byte, NULL, 16);
653         RamPatch[j].Data[k] = (data & 0xFF);
654
655
656     }
657     return A_OK;
658 }
659
660
661 /********************/
662 A_STATUS AthDoParsePS(A_UCHAR *srcbuffer, A_UINT32 srclen)
663 {
664     A_STATUS status;
665     int i;
666     A_BOOL BDADDR_Present = A_ERROR;
667
668     Tag_Count = 0;
669
670     Total_tag_lenght = 0;
671     BDADDR = FALSE;
672
673
674     status = A_ERROR;
675
676     if(NULL != srcbuffer && srclen != 0)
677     {
678         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("File Open Operation Successful\n"));
679
680         status = AthParseFilesUnified(srcbuffer,srclen,MB_FILEFORMAT_PATCH); 
681     }
682     
683
684
685         if(Tag_Count == 0){
686                 Total_tag_lenght = 10;
687
688         }
689         else{
690                 for(i=0; i<Tag_Count; i++){
691                         if(PsTagEntry[i].TagId == 1){
692                                 BDADDR_Present = A_OK;
693                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is present in Patch File \r\n"));
694
695                         }
696                         if(PsTagEntry[i].TagLen % 2 == 1){
697                                 Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen + 1;
698                         }
699                         else{
700                                 Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen;
701                         }
702
703                 }
704         }
705
706         if(Tag_Count > 0 && !BDADDR_Present){
707                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is not present adding 10 extra bytes \r\n"));
708                 Total_tag_lenght=Total_tag_lenght + 10;
709         }
710         Total_tag_lenght = Total_tag_lenght+ 10 + (Tag_Count*4);
711     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Total Length %d\n",Total_tag_lenght));
712
713
714     return status;
715 }
716 char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos)
717 {
718
719     int count;
720     static short flag;
721     char CharRead;
722     count = 0;
723     flag = A_ERROR;
724
725     do
726     {
727         CharRead = AthReadChar(srcbuffer,len,pos);
728         if( CharRead == '\0' ) {
729             buffer[count+1] = '\0';
730             if(count == 0) {
731                 return NULL;
732             }
733             else {
734                 return buffer;
735             }
736         }
737
738         if(CharRead == 13) {
739         } else if(CharRead == 10) {
740             buffer[count] ='\0';  
741             flag = A_ERROR;
742             return buffer;
743         }else {
744             buffer[count++] = CharRead;
745         }
746
747     }
748     while(count < maxlen-1 && CharRead != '\0');
749     buffer[count] = '\0';
750
751     return buffer;
752 }
753
754 static void LoadHeader(A_UCHAR *HCI_PS_Command,A_UCHAR opcode,int length,int index){
755
756         HCI_PS_Command[0]= 0x0B;
757         HCI_PS_Command[1]= 0xFC;
758         HCI_PS_Command[2]= length + 4;
759         HCI_PS_Command[3]= opcode;
760         HCI_PS_Command[4]= (index & 0xFF);
761         HCI_PS_Command[5]= ((index>>8) & 0xFF);
762         HCI_PS_Command[6]= length;
763 }
764
765 /////////////////////////
766 //
767 int AthCreateCommandList(PSCmdPacket **HciPacketList, A_UINT32 *numPackets)
768 {
769
770     A_UINT8 count;
771     A_UINT32 NumcmdEntry = 0; 
772
773     A_UINT32 Crc = 0;
774     *numPackets = 0;
775
776
777     if(Patch_Count > 0)
778             Crc |= RAM_PATCH_REGION;
779     if(Tag_Count > 0)
780             Crc |= RAM_PS_REGION;
781     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("PS Thread Started CRC %x Patch Count %d  Tag Count %d \n",Crc,Patch_Count,Tag_Count));
782     
783     if(Patch_Count || Tag_Count ){
784     NumcmdEntry+=(2 + Patch_Count + Tag_Count); /* CRC Packet + PS Reset Packet  + Patch List + PS List*/
785         if(Patch_Count > 0) {
786             NumcmdEntry++; /* Patch Enable Command */
787         }
788            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size  %d  \r\n",NumcmdEntry,(A_UINT32)sizeof(PSCmdPacket) * NumcmdEntry));
789         (*HciPacketList) = A_MALLOC(sizeof(PSCmdPacket) * NumcmdEntry);
790     if(NULL == *HciPacketList) {
791                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed  \r\n"));
792         }
793         AthPSCreateHCICommand(PS_VERIFY_CRC,Crc,*HciPacketList,numPackets);
794         if(Patch_Count > 0){
795             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Write Patch**** \r\n"));
796                 AthPSCreateHCICommand(WRITE_PATCH,Patch_Count,*HciPacketList,numPackets);
797                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Enable Patch**** \r\n"));
798                 AthPSCreateHCICommand(ENABLE_PATCH,0,*HciPacketList,numPackets);
799         }
800
801         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Reset**** %d[0x%x] \r\n",PS_RAM_SIZE,PS_RAM_SIZE));
802                 AthPSCreateHCICommand(PS_RESET,PS_RAM_SIZE,*HciPacketList,numPackets);
803         if(Tag_Count > 0){
804             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Write**** \r\n"));
805                 AthPSCreateHCICommand(PS_WRITE,Tag_Count,*HciPacketList,numPackets);
806         }    
807     }
808     if(!BDADDR){
809         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR not present \r\n"));
810     
811     }
812     for(count = 0; count < Patch_Count; count++) {
813
814         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing Patch Buffer %d \r\n",count));
815         A_FREE(RamPatch[Patch_Count].Data);
816     }
817
818     for(count = 0; count < Tag_Count; count++) {
819
820         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Freeing PS Buffer %d \r\n",count));
821         A_FREE(PsTagEntry[count].TagData);
822     }
823
824 /* 
825  *  SDIO Transport uses synchronous mode of data transfer 
826  *  So, AthPSOperations() call returns only after receiving the 
827  *  command complete event.
828  */
829     return *numPackets;
830 }
831
832
833 ////////////////////////
834
835 /////////////
836 static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index)
837 {
838     A_UCHAR *HCI_PS_Command;
839     A_UINT32 Length;
840     int i,j;
841     
842     switch(Opcode)
843     {
844     case WRITE_PATCH:
845
846
847          for(i=0;i< Param1;i++){
848
849              HCI_PS_Command = (A_UCHAR *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER);
850              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Allocated Buffer Size %d\n",RamPatch[i].Len+HCI_COMMAND_HEADER));
851                  if(HCI_PS_Command == NULL){
852                      AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
853                          return A_ERROR;
854                  }
855                  memset (HCI_PS_Command, 0, RamPatch[i].Len+HCI_COMMAND_HEADER);
856                  LoadHeader(HCI_PS_Command,Opcode,RamPatch[i].Len,i);
857                  for(j=0;j<RamPatch[i].Len;j++){
858                         HCI_PS_Command[HCI_COMMAND_HEADER+j]=RamPatch[i].Data[j];
859                  }
860                  PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
861                  PSPatchPacket[*index].packetLen = RamPatch[i].Len+HCI_COMMAND_HEADER;
862                  (*index)++;
863
864           
865          }
866
867     break;
868
869     case ENABLE_PATCH:
870
871
872          Length = 0;
873          i= 0;
874          HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
875          if(HCI_PS_Command == NULL){
876              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
877             return A_ERROR;
878          }
879
880          memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
881          LoadHeader(HCI_PS_Command,Opcode,Length,i);
882          PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
883          PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
884          (*index)++;
885
886     break;
887
888     case PS_RESET:
889                         Length = 0x06;
890                         i=0;
891                         HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
892                         if(HCI_PS_Command == NULL){
893                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
894                                 return A_ERROR;
895                         }
896                         memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
897                         LoadHeader(HCI_PS_Command,Opcode,Length,i);
898                         HCI_PS_Command[7]= 0x00;
899                         HCI_PS_Command[Length+HCI_COMMAND_HEADER -2]= (Param1 & 0xFF);
900                         HCI_PS_Command[Length+HCI_COMMAND_HEADER -1]= ((Param1 >>  8) & 0xFF);
901                  PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
902                  PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
903                  (*index)++;
904
905     break;
906
907     case PS_WRITE:
908                        for(i=0;i< Param1;i++){
909                                 if(PsTagEntry[i].TagId ==1)
910                                         BDADDR = TRUE;
911
912                                 HCI_PS_Command = (A_UCHAR *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
913                                 if(HCI_PS_Command == NULL){
914                                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
915                                         return A_ERROR;
916                                 }
917
918                                 memset (HCI_PS_Command, 0, PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
919                                 LoadHeader(HCI_PS_Command,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId);
920
921                                 for(j=0;j<PsTagEntry[i].TagLen;j++){
922                                         HCI_PS_Command[HCI_COMMAND_HEADER+j]=PsTagEntry[i].TagData[j];
923                                 }
924
925                      PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
926                      PSPatchPacket[*index].packetLen = PsTagEntry[i].TagLen+HCI_COMMAND_HEADER;
927                      (*index)++;
928
929                         }
930
931     break;
932
933
934     case PS_VERIFY_CRC:
935                         Length = 0x0;
936
937                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("VALUE of CRC:%d At index %d\r\n",Param1,*index));
938
939                         HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
940                         if(HCI_PS_Command == NULL){
941                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
942                                 return A_ERROR;
943                         }
944                         memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
945                         LoadHeader(HCI_PS_Command,Opcode,Length,Param1);
946
947                  PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
948                  PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
949                  (*index)++;
950
951     break;
952
953     case CHANGE_BDADDR:
954     break;
955     }
956     return A_OK;
957 }
958 A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets)
959 {
960     int i;
961     if(*HciPacketList == NULL) {
962         return A_ERROR;
963     }
964     for(i = 0; i < numPackets;i++) {
965         A_FREE((*HciPacketList)[i].Hcipacket);
966     }  
967     A_FREE(*HciPacketList);
968     return A_OK;
969 }