2 * Name: bcmtool_4330b1.c
4 * Description: Download a patchram files for the HCD format
6 * Copyright (c) 2012-2013, Broadcom Corp., All Rights Reserved.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <sys/types.h>
32 #include <sys/termios.h>
33 #include <sys/ioctl.h>
38 #define HCI_UART_BCSP 1
39 #define HCI_UART_3WIRE 2
40 #define HCI_UART_H4DS 3
42 #define HCIUARTSETPROTO _IOW('U', 200, int)
43 #define HCIUARTGETPROTO _IOR('U', 201, int)
44 #define HCIUARTGETDEVICE _IOR('U', 202, int)
46 /* Pre baudrate change for fast download */
47 #define HIGH_SPEED_PATCHRAM_DOWNLOAD TRUE
49 /* Host Stack Idle Threshold */
50 #define HCILP_IDLE_THRESHOLD 0x01
52 /* Host Controller Idle Threshold */
53 #define HCILP_HC_IDLE_THRESHOLD 0x01
55 /* BT_WAKE Polarity - 0=Active Low, 1= Active High */
56 #define HCILP_BT_WAKE_POLARITY 1
58 /* HOST_WAKE Polarity - 0=Active Low, 1= Active High */
59 #define HCILP_HOST_WAKE_POLARITY 1
62 #define BCM_DISABLE_RF_PWRCTRL FALSE
64 #define RELEASE_DATE "2011.02.07"
67 /* Broadcom AXI patch for BCM4335 chipset only */
68 #define DEPLOY_4335A_AXI_BRIDGE_PATCH TRUE
70 /* The fix for AXI bridge contention between BT and WLAN:
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.
76 #ifndef DEPLOY_4335A_AXI_BRIDGE_PATCH
77 #define DEPLOY_4335A_AXI_BRIDGE_PATCH FALSE
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;
91 #define BD_ADDR_LEN 6 /* Device address length */
92 typedef UINT8 BD_ADDR[BD_ADDR_LEN]; /* Device address */
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)
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)
110 #define HCI_READ_LOCAL_VERSION_INFO (0x0001 | HCI_GRP_INFORMATIONAL_PARAMS)
111 #define HCI_READ_LOCAL_FEATURES (0x0003 | HCI_GRP_INFORMATIONAL_PARAMS)
113 #define HCI_ENABLE_DEV_UNDER_TEST_MODE (0x0003 | HCI_GRP_TESTING_CMDS)
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)
127 #define VOICE_SETTING_MU_LAW_MD 0x0100
128 #define VOICE_SETTING_LINEAR_MD 0x0060
130 #define HCI_ARM_MEM_PEEK 0x04
131 #define HCI_ARM_MEM_POKE 0x05
133 #define BTUI_MAX_STRING_LENGTH_PER_LINE 255
134 #define HCI_BRCM_WRITE_SLEEP_MODE_LENGTH 10
136 #define HCI_BRCM_UPDATE_BAUD_RATE_ENCODED_LENGTH 0x02
137 #define HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH 0x06
139 #define VSC_WRITE_UART_CLOCK_SETTING_LEN 1
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);}
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);}
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;}
163 #define ROTATE_BD_ADDR(p1, p2) \
174 UINT8 vsc_for_pcm_config[5] = { 0x00, 0x00, 0x03, 0x03, 0x00 };
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)
184 UINT8 vsc_for_sco_pcm[5] = { 0x00, 0x01, 0x00, 0x01, 0x01 };
187 Neverland : PCM, 256, short, master ,master
188 Volance : PCM, 256, short, master ,master
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
197 int fd; /* HCI handle */
199 BOOLEAN debug_mode = FALSE; /* Debug Mode Enable */
201 BOOLEAN use_two_stop_bits = FALSE; /* Flag of two stop bits for tty */
203 unsigned char buffer[1024];
205 struct termios termios;
207 void ChangeBaudRate(UINT32 baudrate);
209 void exit_err(UINT8 err)
211 #if ( HIGH_SPEED_PATCHRAM_DOWNLOAD == TRUE )
212 ChangeBaudRate(115200);
217 void print_time(void)
223 rs = clock_gettime(CLOCK_REALTIME, &tp);
224 fprintf(stderr, "[%04d : %06d]\n", tp.tv_sec, tp.tv_nsec / 1000);
229 void dump(unsigned char *out, int len)
233 for (i = 0; i < len; i++) {
237 DEBUG1("%02x ", out[i]);
242 UINT8 SendCommand(UINT16 opcode, UINT8 param_len, UINT8 * p_param_buf)
244 UINT8 pbuf[255] = { 0, };
248 pbuf[1] = (UINT8) (opcode);
249 pbuf[2] = (UINT8) (opcode >> 8);
252 for (i = 0; i < param_len; i++) {
253 pbuf[i + 4] = *p_param_buf++;
256 DEBUG1("Send %d", param_len + 4);
258 dump(pbuf, param_len + 4);
260 write(fd, pbuf, param_len + 4);
264 void expired(int sig)
266 static UINT8 count = 0;
267 DEBUG0("expired try again\n");
268 SendCommand(HCI_RESET, 0, NULL);
273 fprintf(stderr, "[ERR] HCI reset time expired\n");
278 void read_event(int fd, unsigned char *buffer)
284 while ((count = read(fd, &buffer[i], len)) < len) {
292 while ((count = read(fd, &buffer[i], len)) < len) {
300 DEBUG1("\nreceived %d", count);
305 INT32 filesize(char *name)
311 flag = stat(name, &buf);
319 void DisplayProgress(int total, int val)
322 #define PROGRESS_NUM 20
326 char text[PROGRESS_NUM + 2] = { 0, };
329 text[PROGRESS_NUM + 1] = ']';
330 p = (val * PROGRESS_NUM) / total;
332 for (i = 1; i <= p; i++) {
336 for (i = p + 1; i <= PROGRESS_NUM; i++) {
340 for (i = 0; i <= (PROGRESS_NUM + 1); i++) {
341 fprintf(stderr, "%c", text[i]);
344 if (p >= PROGRESS_NUM)
345 fprintf(stderr, " %6d/%6d\n", val, total);
347 fprintf(stderr, " %6d/%6d\r", val, total);
350 fprintf(stderr, " %6d/%6d\n", val, total);
352 fprintf(stderr, " %6d/%6d\r", val, total);
356 #if (DEPLOY_4335A_AXI_BRIDGE_PATCH == TRUE)
357 /* 4335A/B0 AXI BRIDEG lock cookie */
363 #define AXI_LOCK_COOKIE ('B' | 'T'<<8 | '3'<<16 | '5'<<24) /* BT35 */
364 #define AXI_LOCK_FS_NODE "/dev/btlock"
366 static const UINT8 bcm4335a_axi_patch_addr[4] =
368 0x00, 0x02, 0x0d, 0x00
371 static const UINT8 bcm4335a_axi_patch[] =
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
383 /*******************************************************************************
385 ** Function hw_4335_dl_axi_patch
387 ** Description Download 4335Ax/4335B0 AXI BRIDGE patch
389 ** Returns TRUE, if fw patch is sent
392 *******************************************************************************/
393 static UINT8 hw_4335_dl_axi_patch(void)
395 SendCommand(HCI_VSC_WRITE_RAM, sizeof(bcm4335a_axi_patch),
396 (UINT8 *) bcm4335a_axi_patch);
397 read_event(fd, buffer);
399 DEBUG0("hw_4335_dl_axi_patch downloading done");
401 SendCommand(HCI_VSC_LAUNCH_RAM, sizeof(bcm4335a_axi_patch_addr),
402 (UINT8 *) bcm4335a_axi_patch_addr);
403 read_event(fd, buffer);
405 DEBUG0("hw_4335_dl_axi_patch launching done");
410 /*******************************************************************************
412 ** Function hw_4335_release_axi_bridge_lock
414 ** Description Notify kernel to release the AXI BRIDGE lock which was
415 ** acquired earlier in rfkill driver when powering on BT
420 *******************************************************************************/
421 void hw_4335_axi_bridge_lock(void)
426 lock.cookie = AXI_LOCK_COOKIE;
429 fd = open(AXI_LOCK_FS_NODE, O_RDWR);
432 ret = write(fd, &lock, sizeof(lock));
433 DEBUG0("4335 AXI BRIDGE lock");
438 DEBUG1("Failed to unlock AXI LOCK -- can't open %s", AXI_LOCK_FS_NODE);
442 /*******************************************************************************
444 ** Function hw_4335_release_axi_bridge_lock
446 ** Description Notify kernel to release the AXI BRIDGE lock which was
447 ** acquired earlier in rfkill driver when powering on BT
452 *******************************************************************************/
453 void hw_4335_release_axi_bridge_lock(void)
458 lock.cookie = AXI_LOCK_COOKIE;
461 fd = open(AXI_LOCK_FS_NODE, O_RDWR);
464 ret = write(fd, &lock, sizeof(lock));
465 DEBUG0("Releasing 4335 AXI BRIDGE lock");
470 DEBUG1("Failed to unlock AXI LOCK -- can't open %s", AXI_LOCK_FS_NODE);
473 #endif /* (DEPLOY_4335A_AXI_BRIDGE_PATCH == TRUE) */
475 UINT8 DownloadPatchram(char *patchram1)
478 char prm[128] = { 0, };
484 DEBUG1("\n%s\n", patchram1);
487 DEBUG0("HCI reset\n");
488 SendCommand(HCI_RESET, 0, NULL);
490 read_event(fd, buffer);
493 #if (DEPLOY_4335A_AXI_BRIDGE_PATCH == TRUE)
496 SendCommand(HCI_READ_LOCAL_NAME, 0, NULL);
497 read_event(fd, buffer);
499 p_tmp = strstr((char *)(buffer + 7), "BCM4335");
500 DEBUG1( "chip_name [%s]\n", p_tmp);
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();
507 hw_4335_release_axi_bridge_lock();
510 #if ( HIGH_SPEED_PATCHRAM_DOWNLOAD == TRUE )
511 ChangeBaudRate(921600);
514 strncpy(prm, patchram1, 127);
516 fprintf(stderr, "Download Start\n");
518 if ((pFile = fopen(prm, "r")) == NULL) {
519 fprintf(stderr, "file %s could not be opened, error %d\n", prm,
523 FileSize = filesize(prm);
525 SendCommand(HCI_BRCM_DOWNLOAD_MINI_DRV, 0, NULL);
526 read_event(fd, buffer);
530 while (fread(&buffer[1], sizeof(UINT8), 3, pFile)) {
535 fread(&buffer[4], sizeof(UINT8), len, pFile);
537 write(fd, buffer, len + 4);
539 /* dispaly progress */
540 SentSize += (len + 3);
542 DisplayProgress(FileSize, SentSize);
544 /* dispaly progress */
546 read_event(fd, buffer);
551 usleep(100000); /*100ms delay */
553 tcflush(fd, TCIOFLUSH);
554 tcgetattr(fd, &termios);
556 termios.c_cflag |= CRTSCTS;
558 if (use_two_stop_bits)
559 termios.c_cflag |= CSTOPB;
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);
570 /* Send HCI_RESET Command and process event */
571 DEBUG0("HCI reset\n");
572 SendCommand(HCI_RESET, 0, NULL);
574 read_event(fd, buffer);
576 fprintf(stderr, "Download Complete\n");
581 void SetScanEnable(void)
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 */
591 SendCommand(HCI_WRITE_SCAN_ENABLE, 1, &scan_data[0]);
592 read_event(fd, buffer);
597 fprintf(stderr, "Write Audio parameter\n");
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]);
603 SendCommand(HCI_BRCM_WRITE_SCO_PCM_INT_PARAM, 5,
604 (UINT8 *) vsc_for_sco_pcm);
605 read_event(fd, buffer);
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]);
611 SendCommand(VSC_WRITE_PCM_DATA_FORMAT_PARAM, 5,
612 (UINT8 *) vsc_for_pcm_config);
613 read_event(fd, buffer);
616 void SetPcmConf(UINT8 p0, UINT8 p1, UINT8 p2, UINT8 p3, UINT8 p4)
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;
625 void SetScoConf(UINT8 p0, UINT8 p1, UINT8 p2, UINT8 p3, UINT8 p4)
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;
634 void HCILP_Enable(BOOLEAN on)
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 */
656 SendCommand(HCI_BRCM_WRITE_SLEEP_MODE, HCI_BRCM_WRITE_SLEEP_MODE_LENGTH,
658 read_event(fd, buffer);
661 UINT32 uart_speed(UINT32 Speed)
689 void ChangeBaudRate(UINT32 baudrate)
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 */
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);
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);
724 fprintf(stderr, "Not Support baudrate = %ld\n", baudrate);
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;
734 DEBUG1("Change Baudrate %ld\n", baudrate);
736 SendCommand(HCI_BRCM_UPDATE_BAUDRATE_CMD,
737 HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH,
739 read_event(fd, buffer);
741 tcflush(fd, TCIOFLUSH);
742 tcgetattr(fd, &termios);
744 termios.c_cflag |= CRTSCTS;
746 if (use_two_stop_bits)
747 termios.c_cflag |= CSTOPB;
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);
760 void EnableTestMode(void)
762 UINT8 filter_data[] = { 0x02, 0x00, 0x02 };
764 /* bt sleep disable */
767 /* Enable both Inquiry & Page Scans */
770 /* Set Event Filter: Enable Auto Connect */
771 SendCommand(HCI_SET_EVENT_FILTER, 0x03, (UINT8 *) filter_data);
772 read_event(fd, buffer);
774 /* Enable Device under test */
775 SendCommand(HCI_ENABLE_DEV_UNDER_TEST_MODE, 0x0, NULL);
776 read_event(fd, buffer);
778 fprintf(stderr, "Enable Device Under Test\n");
781 void SetLocalFeatures(void)
785 DEBUG0("Read Local Feature\n");
786 SendCommand(HCI_READ_LOCAL_FEATURES, 0, NULL);
787 read_event(fd, buffer);
791 #if (BCM_DISABLE_RF_PWRCTRL == TRUE)
792 fprintf(stderr, "Remove Power Control\n");
793 data[2] &= 0xFB; /* Power contrel */
795 DEBUG0("Write Local Feature\n");
796 SendCommand(VSC_HCI_CMD_SET_LOC_FEATURES_CMD, 0x08, (UINT8 *) data);
797 read_event(fd, buffer);
803 int proto = HCI_UART_H4;
805 if (ioctl(fd, TIOCSETD, &i) < 0) {
806 fprintf(stderr, "Can't set line discipline\n");
810 if (ioctl(fd, HCIUARTSETPROTO, proto) < 0) {
811 fprintf(stderr, "Can't set hci protocol\n");
814 fprintf(stderr, "Done setting line discpline\n");
819 void print_usage(void)
821 fprintf(stderr, "\n");
822 fprintf(stderr, "BRCM BT tool for Linux release %s\n", RELEASE_DATE);
823 fprintf(stderr, "\n");
825 " Usage: bcmtool <tty Device> <command> [command parameter],....\n\n");
827 " -FILE Patchram file name EX) -FILE=BCM43xx_xxx.hcd\n");
829 " -BAUD Set Baudrate EX) -BAUD=3000000\n");
831 " -ADDR BD addr file name EX) -ADDR=.bdaddr\n");
832 fprintf(stderr, " -SCO Enable SCO/PCM config EX) -SCO\n");
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");
838 " -DUT Enable DUT mode(do not use with -LP) EX) -DUT\n");
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");
846 int main(int argc, char *argv[])
854 fprintf(stderr, "BRCM BT tool for Linux release %s\n",
858 #if (DEPLOY_4335A_AXI_BRIDGE_PATCH == TRUE)
859 hw_4335_axi_bridge_lock();
864 if ((fd = open(argv[1], O_RDWR | O_NOCTTY)) == -1) {
865 fprintf(stderr, "port %s could not be opened, error %d\n",
870 tcflush(fd, TCIOFLUSH);
871 tcgetattr(fd, &termios);
873 termios.c_cflag |= CRTSCTS;
875 if (use_two_stop_bits)
876 termios.c_cflag |= CSTOPB;
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);
887 signal(SIGALRM, expired);
889 for (i = 2; i < argc; i++) {
892 if (strstr(ptr, "-DEBUG")) {
894 DEBUG0("DEBUG On\n");
898 if (strstr(ptr, "-CSTOPB")) {
899 use_two_stop_bits = TRUE;
900 DEBUG0("Use two stop bits for tty\n");
905 for (i = 2; i < argc; i++) {
911 fprintf(stderr, "[%d] %s\n", i - 1, ptr);
913 if (strstr(ptr, "-FILE=")) {
918 strncpy(prm_name, ptr, 127);
919 DownloadPatchram(prm_name);
921 } else if (strstr(ptr, "-BAUD=")) {
925 baudrate = atoi(ptr);
927 ChangeBaudRate(baudrate);
928 } else if (strstr(ptr, "-ADDR=")) {
929 char *bdaddr_filename;
932 int bdaddr[10]; /* Displayed BD Address */
934 BD_ADDR local_addr; /* BD Address for write */
939 (ptr, "%02X:%02X:%02X:%02X:%02X:%02X", &bdaddr[0],
940 &bdaddr[1], &bdaddr[2], &bdaddr[3], &bdaddr[4],
942 fprintf(stderr, "-ADDR: Parameter error");
945 bte_write_bdaddr(bdaddr);
948 bdaddr_filename = ptr;
950 if (bdaddr_filename) {
951 pFile = fopen(bdaddr_filename, "r");
955 char text[BTUI_MAX_STRING_LENGTH_PER_LINE];
957 fgets(text, BTUI_MAX_STRING_LENGTH_PER_LINE,
959 sscanf(text, "%02x%02x", &bdaddr[0],
962 fgets(text, BTUI_MAX_STRING_LENGTH_PER_LINE,
964 sscanf(text, "%02x", &bdaddr[2]);
966 fgets(text, BTUI_MAX_STRING_LENGTH_PER_LINE,
968 sscanf(text, "%02x%02x%02x", &bdaddr[3],
969 &bdaddr[4], &bdaddr[5]);
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]);
976 ROTATE_BD_ADDR(local_addr, bdaddr);
978 SendCommand(VSC_WRITE_BD_ADDR, BD_ADDR_LEN,
979 (UINT8 *) local_addr);
980 read_event(fd, buffer);
982 fprintf(stderr, "-ADDR: file open fail\n");
986 } else if (strstr(ptr, "-SCO")) {
989 } else if (strstr(ptr, "-SETSCO=")) {
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],
998 DEBUG0("PCM / SCO configuration value err\n");
1000 ("SCO_Routing,PCM_Interface_Rate,Frame_Type,Sync_Mode,Clock_Mode,LSB_First,Fill_bits,Fill_Method,Fill_Num,Right_Justify\n");
1004 SetScoConf(value[0], value[1], value[2], value[3],
1006 SetPcmConf(value[5], value[6], value[7], value[8],
1009 } else if (strstr(ptr, "-LP")) {
1011 } else if (strstr(ptr, "-DUT")) {
1013 } else if (strstr(ptr, "-FEATURE")) {
1015 } else if (strstr(ptr, "-ATTACH")) {
1020 } else if (strstr(ptr, "-DEBUG")) {
1021 } else if (strstr(ptr, "-CSTOPB")) {
1024 fprintf(stderr, "Invalid parameter(s)!\n");
1029 fprintf(stderr, "EXIT\n");