e9947f6b2bf71fb7e5c44b19a28c39bcffc9ac45
[platform/adaptation/bluetooth-firmware-bcm.git] / tools / bcmtool_4330b1.c
1 /*****************************************************************************
2 **                                                                           
3 **  Name:          bcmtool.c
4 **
5 **  Description:   Download a patchram files for the HCD format
6 **
7 **  Copyright (c) 2000-2009, Broadcom Corp., All Rights Reserved.
8 ******************************************************************************/
9
10 #include <stdio.h>
11 #include <errno.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <stdlib.h>
16 #include <time.h>
17 #include <string.h>
18 #include <signal.h>
19 #include <unistd.h>
20 #include <sys/termios.h>
21 #include <sys/ioctl.h>
22 #include <limits.h>
23
24 #define N_HCI   15
25 #define HCI_UART_H4             0
26 #define HCI_UART_BCSP   1
27 #define HCI_UART_3WIRE  2
28 #define HCI_UART_H4DS   3
29 #define HCI_UART_LL             4
30 #define HCIUARTSETPROTO         _IOW('U', 200, int)
31 #define HCIUARTGETPROTO         _IOR('U', 201, int)
32 #define HCIUARTGETDEVICE        _IOR('U', 202, int)
33
34 /* Pre baudrate change for fast download */
35 #define HIGH_SPEED_PATCHRAM_DOWNLOAD  TRUE
36
37 /* Host Stack Idle Threshold */
38 #define HCILP_IDLE_THRESHOLD          0x01
39
40 /* Host Controller Idle Threshold */
41 #define HCILP_HC_IDLE_THRESHOLD       0x01
42
43 /* BT_WAKE Polarity - 0=Active Low, 1= Active High */
44 #define HCILP_BT_WAKE_POLARITY        1
45
46 /* HOST_WAKE Polarity - 0=Active Low, 1= Active High */
47 #define HCILP_HOST_WAKE_POLARITY      1
48
49 /* Local Feature */
50 #define BCM_DISABLE_RF_PWRCTRL        FALSE
51
52
53
54
55 #define RELEASE_DATE "2011.02.07"
56 #define DEBUG 1
57
58 typedef unsigned char   UINT8;
59 typedef unsigned short  UINT16;
60 typedef unsigned long   UINT32;
61 typedef signed   long   INT32;
62 typedef signed   char   INT8;
63 typedef signed   short  INT16;
64 typedef unsigned char   BOOLEAN;
65
66 #define FALSE    0
67 #define TRUE     (!FALSE)
68
69 #define BD_ADDR_LEN     6                   /* Device address length */
70 typedef UINT8 BD_ADDR[BD_ADDR_LEN];         /* Device address */
71
72
73
74 #define HCI_GRP_LINK_CONTROL_CMDS                 (0x01 << 10)
75 #define HCI_GRP_LINK_POLICY_CMDS                  (0x02 << 10)
76 #define HCI_GRP_HOST_CONT_BASEBAND_CMDS           (0x03 << 10)
77 #define HCI_GRP_INFORMATIONAL_PARAMS              (0x04 << 10)
78 #define HCI_GRP_STATUS_PARAMS                     (0x05 << 10)
79 #define HCI_GRP_TESTING_CMDS                      (0x06 << 10)
80 #define HCI_GRP_L2CAP_CMDS                        (0x07 << 10)
81 #define HCI_GRP_L2CAP_HCI_EVTS                    (0x08 << 10)
82 #define HCI_GRP_VENDOR_SPECIFIC                   (0x3F << 10)
83
84
85 #define HCI_RESET                                 (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
86 #define HCI_SET_EVENT_FILTER                      (0x0005 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
87 #define HCI_READ_SCAN_ENABLE                      (0x0019 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
88 #define HCI_WRITE_SCAN_ENABLE                     (0x001A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
89
90 #define HCI_READ_LOCAL_VERSION_INFO               (0x0001 | HCI_GRP_INFORMATIONAL_PARAMS)
91 #define HCI_READ_LOCAL_FEATURES                   (0x0003 | HCI_GRP_INFORMATIONAL_PARAMS)
92
93 #define HCI_ENABLE_DEV_UNDER_TEST_MODE            (0x0003 | HCI_GRP_TESTING_CMDS)
94
95 #define HCI_BRCM_SUPER_PEEK_POKE                  (0x000A | HCI_GRP_VENDOR_SPECIFIC)
96 #define VSC_WRITE_BD_ADDR                         (0x0001 | HCI_GRP_VENDOR_SPECIFIC)
97 #define VSC_HCI_CMD_SET_LOC_FEATURES_CMD          (0x000B | HCI_GRP_VENDOR_SPECIFIC)
98 #define HCI_BRCM_UPDATE_BAUDRATE_CMD              (0x0018 | HCI_GRP_VENDOR_SPECIFIC)
99 #define HCI_BRCM_WRITE_SCO_PCM_INT_PARAM          (0x001C | HCI_GRP_VENDOR_SPECIFIC)
100 #define VSC_WRITE_PCM_DATA_FORMAT_PARAM           (0x001E | HCI_GRP_VENDOR_SPECIFIC)
101 #define HCI_BRCM_WRITE_SLEEP_MODE                 (0x0027 | HCI_GRP_VENDOR_SPECIFIC)
102 #define HCI_BRCM_DOWNLOAD_MINI_DRV                (0x002E | HCI_GRP_VENDOR_SPECIFIC)
103 #define VSC_WRITE_UART_CLOCK_SETTING              (0x0045 | HCI_GRP_VENDOR_SPECIFIC)
104
105
106 #define VOICE_SETTING_MU_LAW_MD                   0x0100
107 #define VOICE_SETTING_LINEAR_MD                   0x0060
108
109 #define HCI_ARM_MEM_PEEK                          0x04
110 #define HCI_ARM_MEM_POKE                          0x05
111
112 #define BTUI_MAX_STRING_LENGTH_PER_LINE           255
113 #define HCI_BRCM_WRITE_SLEEP_MODE_LENGTH          10
114
115 #define HCI_BRCM_UPDATE_BAUD_RATE_ENCODED_LENGTH    0x02
116 #define HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH  0x06
117
118 #define VSC_WRITE_UART_CLOCK_SETTING_LEN          1
119
120 /* print string with time stamp */
121 #define TDEBUG0(m)                               if(debug_mode) {print_time();fprintf(stderr,m);}
122 #define TDEBUG1(m,n1)                            if(debug_mode) {print_time();fprintf(stderr,m,n1);}
123 #define TDEBUG2(m,n1,n2)                         if(debug_mode) {print_time();fprintf(stderr,m,n1,n2);}
124 #define TDEBUG3(m,n1,n2,n3)                      if(debug_mode) {print_time();fprintf(stderr,m,n1,n2,n3);}
125 #define TDEBUG4(m,n1,n2,n3,n4)                   if(debug_mode) {print_time();fprintf(stderr,m,n1,n2,n3,n4);}
126 #define TDEBUG5(m,n1,n2,n3,n4,n5)                if(debug_mode) {print_time();fprintf(stderr,m,n1,n2,n3,n4,n5);}
127 #define TDEBUG6(m,n1,n2,n3,n4,n5,n6)             if(debug_mode) {print_time();fprintf(stderr,m,n1,n2,n3,n4,n5,n6);}
128
129 /* print just string */
130 #define DEBUG0(m)                               if(debug_mode) {fprintf(stderr,m);}
131 #define DEBUG1(m,n1)                            if(debug_mode) {fprintf(stderr,m,n1);}
132 #define DEBUG2(m,n1,n2)                         if(debug_mode) {fprintf(stderr,m,n1,n2);}
133 #define DEBUG3(m,n1,n2,n3)                      if(debug_mode) {fprintf(stderr,m,n1,n2,n3);}
134 #define DEBUG4(m,n1,n2,n3,n4)                   if(debug_mode) {fprintf(stderr,m,n1,n2,n3,n4);}
135 #define DEBUG5(m,n1,n2,n3,n4,n5)                if(debug_mode) {fprintf(stderr,m,n1,n2,n3,n4,n5);}
136 #define DEBUG6(m,n1,n2,n3,n4,n5,n6)             if(debug_mode) {fprintf(stderr,m,n1,n2,n3,n4,n5,n6);}
137
138
139 #define STREAM_TO_UINT8(u8, p)   {u8 = (UINT8)(*(p)); (p) += 1;}
140 #define STREAM_TO_UINT16(u16, p) {u16 = ((UINT16)(*(p)) + (((UINT16)(*((p) + 1))) << 8)); (p) += 2;}
141 #define STREAM_TO_UINT32(u32, p) {u32 = (((UINT32)(*(p))) + ((((UINT32)(*((p) + 1)))) << 8) + ((((UINT32)(*((p) + 2)))) << 16) + ((((UINT32)(*((p) + 3)))) << 24)); (p) += 4;}
142
143 #define ROTATE_BD_ADDR(p1, p2)    \
144                                                                         do                 \
145                                                                         {                                                       \
146                                                                                 p1[0] = p2[5];          \
147                                                                                 p1[1] = p2[4];          \
148                                                                                 p1[2] = p2[3];          \
149                                                                                 p1[3] = p2[2];          \
150                                                                                 p1[4] = p2[1];          \
151                                                                                 p1[5] = p2[0];          \
152                                                                         } while (0)     
153
154
155 UINT8 vsc_for_pcm_config[5] = {0x00, 0x00, 0x03, 0x03, 0x00};
156 /*
157                     Byte1 -- 0 for MSb first
158                     Byte2 -- 0 Fill value
159                     Byte3 -- 1 Fill option (0:0's, 1:1's , 2:Signed, 3:Programmable)
160                     Byte4 -- 1 Number of fill bits
161                     Byte5 -- 1 Right justified (0 for left justified)
162 */
163
164 UINT8 vsc_for_sco_pcm[5]    = {0x00, 0x01, 0x00, 0x01, 0x01};
165 /*
166                     Neverland : PCM, 256, short, master ,master
167                     Volance   : PCM, 256, short, master ,master
168                     
169                     Byte1 -- 0 for PCM 1 for UART or USB
170                     Byte2 -- 0 : 128, 1: 256, 2:512, 3:1024, 4:2048 Khz
171                     Byte3 -- 0 for short frame sync 1 for long frame sync
172                     Byte4 -- 0 Clock direction 0 for same as sync 1 for opposite direction
173                     Byte5 -- 0 for slave 1 for master
174 */                    
175
176 int fd;    /* HCI handle */
177
178 BOOLEAN debug_mode = FALSE;    /* Debug Mode Enable */
179
180 unsigned char buffer[1024];
181
182 struct termios termios;
183
184 void ChangeBaudRate(UINT32 baudrate);
185
186
187 void exit_err(UINT8 err)
188 {
189 #if ( HIGH_SPEED_PATCHRAM_DOWNLOAD == TRUE )
190     ChangeBaudRate(115200);
191 #endif
192     exit(err);
193 }
194
195 void print_time(void)
196 {
197 #if 0
198     struct timespec tp;
199     int rs;
200
201     rs = clock_gettime(CLOCK_REALTIME,&tp);
202     fprintf(stderr, "[%04d : %06d]\n", tp.tv_sec, tp.tv_nsec/1000);
203     return;
204 #endif
205 }
206
207 void dump(unsigned char *out, int len)
208 {
209     int i;
210     
211     for (i = 0; i < len; i++)
212     {
213         if (!(i % 16)) 
214         {
215             DEBUG0( "\n");
216         }    
217         DEBUG1( "%02x ", out[i]);
218     }
219     DEBUG0( "\n\n");
220 }
221
222 UINT8 SendCommand(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf)
223 {
224     UINT8 pbuf[255] = {0,};
225     UINT8 i=0;
226     
227     pbuf[0] = 0x1;
228     pbuf[1] = (UINT8)(opcode);
229     pbuf[2] = (UINT8)(opcode >>8);
230     pbuf[3] = param_len;
231
232     for (i=0; i<param_len; i++)
233     {        
234         pbuf[i+4] = *p_param_buf++;
235     }
236
237     DEBUG1( "Send %d",param_len+4);     
238
239     dump(pbuf, param_len+4);
240
241         if (write(fd, pbuf, param_len + 4) < 0)
242                 DEBUG0("Fail to write pbuf");
243
244     return 0;
245 }
246
247 void expired(int sig)
248 {
249     static UINT8 count = 0;
250     DEBUG0( "expired try again\n");
251     SendCommand(HCI_RESET, 0, NULL);
252     alarm(1);
253     count++;
254
255     if(count > 3)
256     {
257         fprintf(stderr, "[ERR] HCI reset time expired\n");
258         exit(1);
259     }
260 }
261
262 void read_event(int fd, unsigned char *buffer)
263 {
264     int i = 0;
265     int len = 3;
266     int count;
267
268     while ((count = read(fd, &buffer[i], len)) < len) 
269     {
270         i += count;
271         len -= count;
272     }
273
274     i += count;
275     len = buffer[2];
276
277     while ((count = read(fd, &buffer[i], len)) < len) 
278     {
279         i += count;
280         len -= count;
281     }
282
283 #ifdef DEBUG
284     count += i;
285
286     DEBUG1( "\nreceived %d", count);
287     dump(buffer, count);
288 #endif
289 }
290
291 INT32 filesize (char *name) 
292 {
293     INT32 size;
294     int flag;
295     struct stat buf;
296
297     flag = stat (name,&buf);
298     if (flag == -1) 
299         return -1;
300
301     size = buf.st_size;
302     return (size);
303 }
304
305 void DisplayProgress(int total, int val)
306 {
307 #if 0
308     #define PROGRESS_NUM 20
309     
310     int p;
311     int i;
312     char text[PROGRESS_NUM+2]={0,};
313     
314     text[0]='[';
315     text[PROGRESS_NUM+1]=']';
316     p=(val*PROGRESS_NUM)/total;
317     
318     for ( i=1; i<=p; i++)
319     {
320         text[i]='=';
321     }
322     
323     for ( i=p+1; i<=PROGRESS_NUM; i++)
324     {
325         text[i]=' ';
326     }
327     
328     
329     for ( i=0; i<=(PROGRESS_NUM+1); i++)
330     {
331         fprintf(stderr, "%c",text[i]);
332     }
333     
334     if( p >= PROGRESS_NUM)
335         fprintf(stderr, "  %6d/%6d\n",val,total);
336     else
337         fprintf(stderr, "  %6d/%6d\r",val,total);
338 #else
339     if( val == total)
340         fprintf(stderr, " %6d/%6d\n",val,total);
341     else
342         fprintf(stderr, " %6d/%6d\r",val,total);
343 #endif
344 }
345
346 UINT8 DownloadPatchram( char *patchram1 )
347 {
348     UINT32 len;
349     char   prm[128] ={0,};
350     FILE* pFile = NULL;
351         size_t size;
352
353     INT32 FileSize=0;
354     INT32 SentSize=0;
355     
356     DEBUG1( "\n%s\n", patchram1);
357
358     /* HCI reset */
359     DEBUG0( "HCI reset\n");
360     SendCommand(HCI_RESET, 0, NULL);
361     alarm(1);
362     read_event(fd, buffer);
363     alarm(0);
364     
365 #if ( HIGH_SPEED_PATCHRAM_DOWNLOAD == TRUE )
366     ChangeBaudRate(921600);
367 #endif
368
369     strcpy(prm, patchram1);    
370
371     fprintf(stderr, "Download Start\n");
372
373     if ((pFile = fopen(prm, "r")) == NULL) 
374     {
375         fprintf(stderr, "file %s could not be opened, error %d\n", prm, errno);
376         exit_err(1);
377     }
378     FileSize = filesize(prm);
379         
380     SendCommand(HCI_BRCM_DOWNLOAD_MINI_DRV, 0, NULL);
381     read_event(fd, buffer);
382
383         usleep(50000);
384
385     while (fread(&buffer[1], sizeof(UINT8), 3 ,pFile)) 
386     {
387         buffer[0] = 0x01;
388
389         len = buffer[3];
390
391                 size = fread(&buffer[4], sizeof(UINT8), len, pFile);
392                 fprintf(stderr, "fread size: %d\n", size);
393
394                 size = write(fd, buffer, len + 4);
395                 fprintf(stderr, "write size: %d\n", size);
396
397         /* dispaly progress*/
398         SentSize += (len + 3);
399         DisplayProgress(FileSize,SentSize);
400         /* dispaly progress*/
401         
402         read_event(fd, buffer);
403
404     }
405     fclose(pFile);
406
407     usleep(100000);    /*100ms delay */
408
409     tcflush(fd, TCIOFLUSH);
410     tcgetattr(fd, &termios);
411     cfmakeraw(&termios);
412     termios.c_cflag |= CRTSCTS;
413     tcsetattr(fd, TCSANOW, &termios);
414     tcflush(fd, TCIOFLUSH);
415     tcsetattr(fd, TCSANOW, &termios);
416     tcflush(fd, TCIOFLUSH);
417     tcflush(fd, TCIOFLUSH);
418     cfsetospeed(&termios, B115200);
419     cfsetispeed(&termios, B115200);
420     tcsetattr(fd, TCSANOW, &termios);
421
422     /* Send HCI_RESET Command and process event */
423     DEBUG0( "HCI reset\n");
424     SendCommand(HCI_RESET, 0, NULL);
425     alarm(1);
426     read_event(fd, buffer);
427     alarm(0);
428     fprintf(stderr,"Download Complete\n");
429
430     return 0;
431 }
432
433 void SetScanEnable(void)
434 {
435     UINT8 scan_data[1] ;
436
437    /* 0x00: No scan enabled                            */
438    /* 0x01: Inquiry scan enabled  | Page scan disabled */
439    /* 0x02: Inquiry scan disabled | Page scan enabled  */
440    /* 0x03: Inquiry scan enabled  | Page scan enabled  */
441
442     scan_data[0]= 0x03;
443     SendCommand(HCI_WRITE_SCAN_ENABLE, 1, &scan_data[0]);
444     read_event(fd, buffer);
445 }
446
447 void SetAudio(void)
448 {
449     fprintf(stderr,"Write Audio parameter\n");
450
451     DEBUG5( "vsc_for_sco_pcm = {%d,%d,%d,%d,%d}\n", vsc_for_sco_pcm[0],
452                                          vsc_for_sco_pcm[1],vsc_for_sco_pcm[2],
453                                          vsc_for_sco_pcm[3],vsc_for_sco_pcm[4]);
454
455     SendCommand(HCI_BRCM_WRITE_SCO_PCM_INT_PARAM, 5, (UINT8 *)vsc_for_sco_pcm);
456     read_event(fd, buffer);
457
458     DEBUG5( "vsc_for_pcm_config = {%d,%d,%d,%d,%d}\n", vsc_for_pcm_config[0],
459                                         vsc_for_pcm_config[1], vsc_for_pcm_config[2],
460                                         vsc_for_pcm_config[3], vsc_for_pcm_config[4]);
461
462     SendCommand(VSC_WRITE_PCM_DATA_FORMAT_PARAM, 5, (UINT8 *)vsc_for_pcm_config);
463     read_event(fd, buffer);
464 }
465
466 void SetPcmConf( UINT8 p0, UINT8 p1, UINT8 p2, UINT8 p3, UINT8 p4 )
467 {
468     vsc_for_pcm_config[0] = p0;
469     vsc_for_pcm_config[1] = p1;
470     vsc_for_pcm_config[2] = p2;
471     vsc_for_pcm_config[3] = p3;
472     vsc_for_pcm_config[4] = p4;
473 }
474
475 void SetScoConf( UINT8 p0, UINT8 p1, UINT8 p2, UINT8 p3, UINT8 p4 )
476 {
477     vsc_for_sco_pcm[0] = p0;
478     vsc_for_sco_pcm[1] = p1;
479     vsc_for_sco_pcm[2] = p2;
480     vsc_for_sco_pcm[3] = p3;
481     vsc_for_sco_pcm[4] = p4;
482 }
483
484 void HCILP_Enable(BOOLEAN on)
485 {
486     fprintf(stderr,"Set Low Power mode %d\n",on);
487     UINT8 data[HCI_BRCM_WRITE_SLEEP_MODE_LENGTH] = {
488     0x01,                        /* Sleep Mode algorithm 1 */
489     HCILP_IDLE_THRESHOLD,        /* Host Idle Treshold in 300ms */
490     HCILP_HC_IDLE_THRESHOLD,     /* Host Controller Idle Treshold in 300ms */ /* this should be less than scan interval.*/
491     HCILP_BT_WAKE_POLARITY,      /* BT_WAKE Polarity - 0=Active Low, 1= Active High*/
492     HCILP_HOST_WAKE_POLARITY,    /* HOST_WAKE Polarity - 0=Active Low, 1= Active High */
493     0x01,                        /* Allow host Sleep during SCO */
494     0x01,                        /* Combine Sleep Mode and LPM - The device will not sleep in mode 0 if this flag is set to 1,*/
495     0x00,                        /* UART_TXD Tri-State : 0x00 = Do not tri-state UART_TXD in sleep mode */
496     0x00,                        /* NA to Mode 1 */
497     0x00,                        /* NA to Mode 1 */
498     };
499
500     if(on)
501     {
502         data[0] = 0x01;
503     }
504     else
505     {
506         data[0] = 0x00;
507     }
508
509     SendCommand(HCI_BRCM_WRITE_SLEEP_MODE, HCI_BRCM_WRITE_SLEEP_MODE_LENGTH, (UINT8 *)data);
510     read_event(fd, buffer);
511 }
512
513 UINT32 uart_speed(UINT32 Speed)
514 {
515         switch (Speed) 
516         {
517         case 115200:
518                 return B115200;
519         case 230400:
520                 return B230400;
521         case 460800:
522                 return B460800;
523         case 921600:
524                 return B921600;
525         case 1000000:
526                 return B1000000;
527         case 1500000:
528                 return B1500000;
529         case 2000000:
530                 return B2000000;
531         case 2500000:
532                 return B2500000;
533         case 3000000:
534                 return B3000000;
535         case 4000000:
536                 return B4000000;
537         default:
538                 return B115200;
539         }
540 }
541
542 void ChangeBaudRate(UINT32 baudrate)
543 {
544     UINT8 hci_data[HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
545     UINT8 uart_clock_24 = 0x2;    /* 0x1 - UART Clock 48MHz, 0x2 - UART Clock 24MHz */    
546     UINT8 uart_clock_48 = 0x1;    /* 0x1 - UART Clock 48MHz, 0x2 - UART Clock 24MHz */
547
548     switch(baudrate)
549     {
550         case 115200:
551         case 230400:
552         case 460800:
553         case 921600:
554         case 1000000:
555         case 1500000:
556         case 2000000:
557         case 2500000:
558             /* Write UART Clock setting of 24MHz */
559             DEBUG0( "Change UART_CLOCK 24Mhz\n");    
560             SendCommand( VSC_WRITE_UART_CLOCK_SETTING, VSC_WRITE_UART_CLOCK_SETTING_LEN, (UINT8 *)&uart_clock_24);
561             read_event(fd, buffer);        
562             break;        
563
564         case 3000000:
565         case 4000000:
566             /* Write UART Clock setting of 48MHz */
567             DEBUG0( "Change UART_CLOCK 48Mh\nz");    
568             SendCommand( VSC_WRITE_UART_CLOCK_SETTING, VSC_WRITE_UART_CLOCK_SETTING_LEN, (UINT8 *)&uart_clock_48);
569             read_event(fd, buffer);        
570             break;
571             
572         default:
573             fprintf(stderr,"Not Support baudrate = %ld\n", baudrate);
574             exit_err(1);
575             break;
576     }
577
578     hci_data[2] = baudrate & 0xFF;
579     hci_data[3] = (baudrate >> 8) & 0xFF;
580     hci_data[4] = (baudrate >> 16) & 0xFF;
581     hci_data[5] = (baudrate >> 24) & 0xFF;
582     
583     DEBUG1( "Change Baudrate %ld\n",baudrate);    
584
585     SendCommand( HCI_BRCM_UPDATE_BAUDRATE_CMD, HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH, (UINT8 *)hci_data);
586     read_event(fd, buffer);
587
588     
589     tcflush(fd, TCIOFLUSH);
590     tcgetattr(fd, &termios);
591     cfmakeraw(&termios);
592     termios.c_cflag |= CRTSCTS;
593     tcsetattr(fd, TCSANOW, &termios);
594     tcflush(fd, TCIOFLUSH);
595     tcsetattr(fd, TCSANOW, &termios);
596     tcflush(fd, TCIOFLUSH);
597     tcflush(fd, TCIOFLUSH);
598     cfsetospeed(&termios, uart_speed(baudrate));
599     cfsetispeed(&termios, uart_speed(baudrate));
600     tcsetattr(fd, TCSANOW, &termios);
601
602 }
603
604 void EnableTestMode(void)
605 {
606     UINT8 filter_data[] = { 0x02, 0x00, 0x02 };
607     
608     /* bt sleep  disable */
609     HCILP_Enable(FALSE);
610
611     /* Enable both Inquiry & Page Scans */
612     SetScanEnable();
613
614     /* Set Event Filter: Enable Auto Connect */
615     SendCommand( HCI_SET_EVENT_FILTER, 0x03, (UINT8 *)filter_data);
616     read_event(fd, buffer);
617
618     /* Enable Device under test */
619     SendCommand( HCI_ENABLE_DEV_UNDER_TEST_MODE, 0x0, NULL);
620     read_event(fd, buffer);
621
622     fprintf(stderr,"Enable Device Under Test\n");
623 }
624
625 void SetLocalFeatures(void)
626 {
627     UINT8  *data = NULL;
628
629     DEBUG0("Read Local Feature\n");    
630     SendCommand(HCI_READ_LOCAL_FEATURES, 0, NULL);
631     read_event(fd, buffer);
632
633     data = &buffer[7];
634
635 #if (BCM_DISABLE_RF_PWRCTRL == TRUE)
636     fprintf(stderr,"Remove Power Control\n");
637     data[2] &= 0xFB;    /* Power contrel */
638 #endif
639     DEBUG0("Write Local Feature\n");    
640     SendCommand(VSC_HCI_CMD_SET_LOC_FEATURES_CMD, 0x08, (UINT8 *)data);
641     read_event(fd, buffer);
642 }
643
644 void EnbleHCI(void)
645 {
646     int i = N_HCI;
647     int proto = HCI_UART_H4;
648
649     if (ioctl(fd, TIOCSETD, &i) < 0) 
650     {
651         fprintf(stderr, "Can't set line discipline\n");
652         return;
653     }
654     
655     if (ioctl(fd, HCIUARTSETPROTO, proto) < 0) 
656     {
657         fprintf(stderr, "Can't set hci protocol\n");
658         return;
659     }
660     fprintf(stderr, "Done setting line discpline\n");
661     return;
662     
663 }
664 void print_usage( void )
665 {
666     fprintf(stderr,"\n");
667     fprintf(stderr,"BRCM BT tool for Linux    release %s\n",RELEASE_DATE);
668     fprintf(stderr,"\n");
669     fprintf(stderr," Usage: bcmtool <tty Device> <command> [command parameter],....\n\n");    
670     fprintf(stderr,"  -FILE    Patchram file name     EX) -FILE=BCM43xx_xxx.hcd\n");
671     fprintf(stderr,"  -BAUD    Set Baudrate           EX) -BAUD=3000000\n");
672     fprintf(stderr,"  -ADDR    BD addr file name      EX) -ADDR=.bdaddr\n");
673     fprintf(stderr,"  -SCO     Enable SCO/PCM config  EX) -SCO\n");
674     fprintf(stderr,"  -SETSCO  SCO/PCM values verify  EX) -SETSCO=0,1,0,1,1,0,0,3,3,0\n");
675     fprintf(stderr,"  -LP      Enable Low power       EX) -LP\n");
676     fprintf(stderr,"  -FEATURE Set local Feature      EX) -FEATURE\n");
677     fprintf(stderr,"  -DUT     Enable DUT mode(do not use with -LP) EX) -DUT\n");
678     fprintf(stderr,"  -ATTACH  Attach BT controller to BlueZ stack  EX) -ATTACH\n");    
679     fprintf(stderr,"  -DEBUG   Debug message          EX) -DEBUG\n");
680     fprintf(stderr,"\n");
681 }
682
683 int main(int argc, char *argv[])
684 {
685     UINT8 i = 0;
686     
687     if (argc < 2) 
688     {
689         print_usage();
690         exit(1);
691     }
692     else
693     {
694         fprintf(stderr,"BRCM BT tool for Linux    release %s\n",RELEASE_DATE);
695     }
696     
697     /* Open dev port */
698     if ((fd = open(argv[1], O_RDWR | O_NOCTTY)) == -1) 
699     {
700         fprintf(stderr, "port %s could not be opened, error %d\n", argv[1], errno);
701         exit(2);
702     }
703     
704     tcflush(fd, TCIOFLUSH);
705     tcgetattr(fd, &termios);
706     cfmakeraw(&termios);
707     termios.c_cflag |= CRTSCTS;
708     tcsetattr(fd, TCSANOW, &termios);
709     tcflush(fd, TCIOFLUSH);
710     tcsetattr(fd, TCSANOW, &termios);
711     tcflush(fd, TCIOFLUSH);
712     tcflush(fd, TCIOFLUSH);
713     cfsetospeed(&termios, B115200);
714     cfsetispeed(&termios, B115200);
715     tcsetattr(fd, TCSANOW, &termios);
716     
717     signal(SIGALRM, expired);
718
719     for( i=2; i<argc; i++ )
720     {
721         char *ptr = argv[i];
722
723         if( strstr(ptr,"-DEBUG") )
724         {
725             debug_mode = TRUE;
726             DEBUG0("DEBUG On\n");
727             break;
728         }
729     }
730     
731     for( i=2; i<argc; i++ )
732     {
733         char *ptr = argv[i];
734         
735         if(ptr == NULL)
736                 continue;
737         
738         fprintf(stderr,"[%d] %s\n", i-1, ptr);
739         
740         if( strstr(ptr,"-FILE=") )
741         {
742             char prm_name[128];
743
744             ptr += 6;
745
746             strncpy(prm_name,ptr, 127);
747             DownloadPatchram( prm_name );
748
749         }
750         else if( strstr(ptr,"-BAUD=") )
751         {
752             UINT32  baudrate;
753
754             ptr += 6;
755             baudrate = atoi(ptr);
756
757             ChangeBaudRate(baudrate);
758         }
759         else if( strstr(ptr,"-ADDR=") )
760         {
761             char *bdaddr_filename;
762             FILE* pFile = NULL;
763
764             int bdaddr[10];         /* Displayed BD Address */
765             
766             BD_ADDR local_addr;       /* BD Address for write */
767
768 #if 0            
769             ptr += 6;
770             if( sscanf(ptr,"%02X:%02X:%02X:%02X:%02X:%02X",&bdaddr[0],&bdaddr[1],&bdaddr[2],&bdaddr[3],&bdaddr[4],&bdaddr[5]) != 6 )
771             {
772                 fprintf(stderr,"-ADDR: Parameter error");
773                 exit_err(1);
774             }
775             bte_write_bdaddr(bdaddr);
776 #endif
777             ptr += 6;
778             bdaddr_filename = ptr;
779
780             if(bdaddr_filename)
781             {
782                pFile = fopen(bdaddr_filename, "r");
783             }          
784
785             if(pFile)
786             {
787                 char text[BTUI_MAX_STRING_LENGTH_PER_LINE];
788
789                                 if (!fgets(text, BTUI_MAX_STRING_LENGTH_PER_LINE, pFile))
790                                         fprintf(stderr, "fail to fgets");
791                 sscanf(text,"%02x%02x",&bdaddr[0],&bdaddr[1]);
792
793                                 if (!fgets(text, BTUI_MAX_STRING_LENGTH_PER_LINE, pFile))
794                                         fprintf(stderr, "fail to fgets");
795                 sscanf(text,"%02x",&bdaddr[2]);
796
797                                 if (!fgets(text, BTUI_MAX_STRING_LENGTH_PER_LINE, pFile))
798                                         fprintf(stderr, "fail to fgets");
799                 sscanf(text,"%02x%02x%02x",&bdaddr[3],&bdaddr[4],&bdaddr[5]);
800
801                 fprintf(stderr,"Writing B/D Address = %02X:%02X:%02X:%02X:%02X:%02X\n",bdaddr[0],bdaddr[1],bdaddr[2],bdaddr[3],bdaddr[4],bdaddr[5]);
802
803                 ROTATE_BD_ADDR(local_addr,bdaddr);
804
805                 SendCommand(VSC_WRITE_BD_ADDR, BD_ADDR_LEN, (UINT8 *)local_addr);
806                 read_event(fd, buffer);
807             }    
808             else
809             {
810                 fprintf(stderr, "-ADDR: file open fail\n");
811                 exit_err(1);
812             }
813
814         }
815         else if( strstr(ptr,"-SCO") )
816         {
817             SetAudio();
818         
819         }
820         else if( strstr(ptr,"-SETSCO=") )
821         {
822             ptr += 8;
823             int value[10];
824             
825             if( sscanf(ptr,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",&value[0],&value[1],&value[2],&value[3],&value[4],
826                                                            &value[5],&value[6],&value[7],&value[8],&value[9]) != 10 )
827             {
828                 DEBUG0("PCM / SCO configuration value err\n");
829                 DEBUG0("SCO_Routing,PCM_Interface_Rate,Frame_Type,Sync_Mode,Clock_Mode,LSB_First,Fill_bits,Fill_Method,Fill_Num,Right_Justify\n");
830                 exit_err(1);
831             }
832
833             SetScoConf( value[0],value[1],value[2],value[3],value[4] );
834             SetPcmConf( value[5],value[6],value[7],value[8],value[9] );
835             SetAudio();
836         }
837         else if( strstr(ptr,"-LP") )
838         {
839             HCILP_Enable(TRUE);
840         }
841         else if( strstr(ptr,"-DUT") )
842         {
843             EnableTestMode();
844         }
845         else if( strstr(ptr,"-FEATURE") )
846         {
847             SetLocalFeatures();
848         }
849         else if( strstr(ptr,"-ATTACH") )
850         {
851             EnbleHCI();
852             while (1) 
853             {
854                 sleep(UINT_MAX);
855             }            
856         }
857         else if( strstr(ptr,"-DEBUG") )
858         {
859
860         }
861         else
862         {
863             fprintf(stderr,"Invalid parameter(s)!\n");
864             exit_err(1);
865         }
866     }
867
868     fprintf(stderr, "EXIT\n");
869     close(fd);
870     exit(0);
871
872     return 0;
873 }