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