xref: /OK3568_Linux_fs/external/rkwifibt/tools/brcm_tools/brcm_patchram_plus1.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*******************************************************************************
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  *  Copyright (C) 2009-2011 Broadcom Corporation
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Licensed under the Apache License, Version 2.0 (the "License");
6*4882a593Smuzhiyun  *  you may not use this file except in compliance with the License.
7*4882a593Smuzhiyun  *  You may obtain a copy of the License at
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  *      http://www.apache.org/licenses/LICENSE-2.0
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  *  Unless required by applicable law or agreed to in writing, software
12*4882a593Smuzhiyun  *  distributed under the License is distributed on an "AS IS" BASIS,
13*4882a593Smuzhiyun  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*4882a593Smuzhiyun  *  See the License for the specific language governing permissions and
15*4882a593Smuzhiyun  *  limitations under the License.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  ******************************************************************************/
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*****************************************************************************
20*4882a593Smuzhiyun **
21*4882a593Smuzhiyun **  Name:          brcm_patchram_plus.c
22*4882a593Smuzhiyun **
23*4882a593Smuzhiyun **  Description:   This program downloads a patchram files in the HCD format
24*4882a593Smuzhiyun **                 to Broadcom Bluetooth based silicon and combo chips and
25*4882a593Smuzhiyun **				   and other utility functions.
26*4882a593Smuzhiyun **
27*4882a593Smuzhiyun **                 It can be invoked from the command line in the form
28*4882a593Smuzhiyun **						<-d> to print a debug log
29*4882a593Smuzhiyun **						<--patchram patchram_file>
30*4882a593Smuzhiyun **						<--baudrate baud_rate>
31*4882a593Smuzhiyun **						<--bd_addr bd_address>
32*4882a593Smuzhiyun **						<--enable_lpm>
33*4882a593Smuzhiyun **						<--enable_hci>
34*4882a593Smuzhiyun **						<--use_baudrate_for_download>
35*4882a593Smuzhiyun **						<--scopcm=sco_routing,pcm_interface_rate,frame_type,
36*4882a593Smuzhiyun **							sync_mode,clock_mode,lsb_first,fill_bits,
37*4882a593Smuzhiyun **							fill_method,fill_num,right_justify>
38*4882a593Smuzhiyun **
39*4882a593Smuzhiyun **							Where
40*4882a593Smuzhiyun **
41*4882a593Smuzhiyun **							sco_routing is 0 for PCM, 1 for Transport,
42*4882a593Smuzhiyun **							2 for Codec and 3 for I2S,
43*4882a593Smuzhiyun **
44*4882a593Smuzhiyun **							pcm_interface_rate is 0 for 128KBps, 1 for
45*4882a593Smuzhiyun **							256 KBps, 2 for 512KBps, 3 for 1024KBps,
46*4882a593Smuzhiyun **							and 4 for 2048Kbps,
47*4882a593Smuzhiyun **
48*4882a593Smuzhiyun **							frame_type is 0 for short and 1 for long,
49*4882a593Smuzhiyun **
50*4882a593Smuzhiyun **							sync_mode is 0 for slave and 1 for master,
51*4882a593Smuzhiyun **
52*4882a593Smuzhiyun **							clock_mode is 0 for slabe and 1 for master,
53*4882a593Smuzhiyun **
54*4882a593Smuzhiyun **							lsb_first is 0 for false aand 1 for true,
55*4882a593Smuzhiyun **
56*4882a593Smuzhiyun **							fill_bits is the value in decimal for unused bits,
57*4882a593Smuzhiyun **
58*4882a593Smuzhiyun **							fill_method is 0 for 0's and 1 for 1's, 2 for
59*4882a593Smuzhiyun **								signed and 3 for programmable,
60*4882a593Smuzhiyun **
61*4882a593Smuzhiyun **							fill_num is the number or bits to fill,
62*4882a593Smuzhiyun **
63*4882a593Smuzhiyun **							right_justify is 0 for false and 1 for true
64*4882a593Smuzhiyun **
65*4882a593Smuzhiyun **						<--i2s=i2s_enable,is_master,sample_rate,clock_rate>
66*4882a593Smuzhiyun **
67*4882a593Smuzhiyun **							Where
68*4882a593Smuzhiyun **
69*4882a593Smuzhiyun **							i2s_enable is 0 for disable and 1 for enable,
70*4882a593Smuzhiyun **
71*4882a593Smuzhiyun **							is_master is 0 for slave and 1 for master,
72*4882a593Smuzhiyun **
73*4882a593Smuzhiyun **							sample_rate is 0 for 8KHz, 1 for 16Khz and
74*4882a593Smuzhiyun **								2 for 4 KHz,
75*4882a593Smuzhiyun **
76*4882a593Smuzhiyun **							clock_rate is 0 for 128KHz, 1 for 256KHz, 3 for
77*4882a593Smuzhiyun **								1024 KHz and 4 for 2048 KHz.
78*4882a593Smuzhiyun **
79*4882a593Smuzhiyun **						<--no2bytes skips waiting for two byte confirmation
80*4882a593Smuzhiyun **							before starting patchram download. Newer chips
81*4882a593Smuzhiyun **                          do not generate these two bytes.>
82*4882a593Smuzhiyun **						<--tosleep=number of microsseconds to sleep before
83*4882a593Smuzhiyun **							patchram download begins.>
84*4882a593Smuzhiyun **						uart_device_name
85*4882a593Smuzhiyun **
86*4882a593Smuzhiyun **                 For example:
87*4882a593Smuzhiyun **
88*4882a593Smuzhiyun **                 brcm_patchram_plus -d --patchram  \
89*4882a593Smuzhiyun **						BCM2045B2_002.002.011.0348.0349.hcd /dev/ttyHS0
90*4882a593Smuzhiyun **
91*4882a593Smuzhiyun **                 It will return 0 for success and a number greater than 0
92*4882a593Smuzhiyun **                 for any errors.
93*4882a593Smuzhiyun **
94*4882a593Smuzhiyun **                 For Android, this program invoked using a
95*4882a593Smuzhiyun **                 "system(2)" call from the beginning of the bt_enable
96*4882a593Smuzhiyun **                 function inside the file
97*4882a593Smuzhiyun **                 system/bluetooth/bluedroid/bluetooth.c.
98*4882a593Smuzhiyun **
99*4882a593Smuzhiyun **                 If the Android system property "ro.bt.bcm_bdaddr_path" is
100*4882a593Smuzhiyun **                 set, then the bd_addr will be read from this path.
101*4882a593Smuzhiyun **                 This is overridden by --bd_addr on the command line.
102*4882a593Smuzhiyun **
103*4882a593Smuzhiyun ******************************************************************************/
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun // TODO: Integrate BCM support into Bluez hciattach
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun #include <ctype.h>
108*4882a593Smuzhiyun #include <stdio.h>
109*4882a593Smuzhiyun #include <getopt.h>
110*4882a593Smuzhiyun #include <errno.h>
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun #include <sys/types.h>
113*4882a593Smuzhiyun #include <sys/stat.h>
114*4882a593Smuzhiyun #include <fcntl.h>
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun #include <stdlib.h>
117*4882a593Smuzhiyun #include <time.h>
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #ifdef ANDROID
120*4882a593Smuzhiyun #include <termios.h>
121*4882a593Smuzhiyun #else
122*4882a593Smuzhiyun #include <sys/termios.h>
123*4882a593Smuzhiyun #include <sys/ioctl.h>
124*4882a593Smuzhiyun #include <limits.h>
125*4882a593Smuzhiyun #include <unistd.h>
126*4882a593Smuzhiyun #endif
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun #include <string.h>
129*4882a593Smuzhiyun #include <signal.h>
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun #ifdef ANDROID
132*4882a593Smuzhiyun #include <cutils/properties.h>
133*4882a593Smuzhiyun #define LOG_TAG "brcm_patchram_plus"
134*4882a593Smuzhiyun #include <cutils/log.h>
135*4882a593Smuzhiyun #undef printf
136*4882a593Smuzhiyun #define printf ALOGD
137*4882a593Smuzhiyun #undef fprintf
138*4882a593Smuzhiyun #define fprintf(x, ...) \
139*4882a593Smuzhiyun   { if(x==stderr) ALOGE(__VA_ARGS__); else fprintf(x, __VA_ARGS__); }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun #endif //ANDROID
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun #ifndef N_HCI
144*4882a593Smuzhiyun #define N_HCI	15
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun #define HCIUARTSETPROTO		_IOW('U', 200, int)
148*4882a593Smuzhiyun #define HCIUARTGETPROTO		_IOR('U', 201, int)
149*4882a593Smuzhiyun #define HCIUARTGETDEVICE	_IOR('U', 202, int)
150*4882a593Smuzhiyun #define AP_NAME_SUFFIX_LEN 18
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun #define HCI_UART_H4		0
153*4882a593Smuzhiyun #define HCI_UART_BCSP	1
154*4882a593Smuzhiyun #define HCI_UART_3WIRE	2
155*4882a593Smuzhiyun #define HCI_UART_H4DS	3
156*4882a593Smuzhiyun #define HCI_UART_LL		4
157*4882a593Smuzhiyun #define LOCAL_NAME_BUFFER_LEN                   32
158*4882a593Smuzhiyun #define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING      6
159*4882a593Smuzhiyun typedef unsigned char uchar;
160*4882a593Smuzhiyun /* AMPAK FW auto detection table */
161*4882a593Smuzhiyun typedef struct {
162*4882a593Smuzhiyun     char *chip_id;
163*4882a593Smuzhiyun     char *updated_chip_id;
164*4882a593Smuzhiyun } fw_auto_detection_entry_t;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun #define FW_TABLE_VERSION "v1.1 20161117"
167*4882a593Smuzhiyun static const fw_auto_detection_entry_t fw_auto_detection_table[] = {
168*4882a593Smuzhiyun 	{"4343A0","bcm43438a0"},    //AP6212
169*4882a593Smuzhiyun 	{"BCM43430A1","BCM43430A1"}, //AP6212A
170*4882a593Smuzhiyun 	{"BCM20702A","BCM20710A1"}, //AP6210B
171*4882a593Smuzhiyun 	{"BCM4335C0","bcm4339a0"}, //AP6335
172*4882a593Smuzhiyun 	{"BCM4330B1","BCM40183B2"}, //AP6330
173*4882a593Smuzhiyun 	{"BCM4324B3","BCM43241B4"}, //AP62X2
174*4882a593Smuzhiyun 	{"BCM4350C0","bcm4354a1"}, //AP6354
175*4882a593Smuzhiyun 	{"BCM4345C5","BCM4345C5"}, //AP6256
176*4882a593Smuzhiyun 	{"BCM4354A2","BCM4356A2"}, //AP6356
177*4882a593Smuzhiyun 	{"BCM4345C0","BCM4345C0"}, //AP6255
178*4882a593Smuzhiyun 	//{"BCM43341B0","BCM43341B0"}, //AP6234
179*4882a593Smuzhiyun 	//{"BCM2076B1","BCM2076B1"}, //AP6476
180*4882a593Smuzhiyun 	{"BCM43430B0","BCM4343B0"}, //AP6236
181*4882a593Smuzhiyun 	{"BCM4359C0","BCM4359C0"},  //AP6359
182*4882a593Smuzhiyun 	{"BCM4349B1","BCM4359B1"},  //AP6359
183*4882a593Smuzhiyun 	{"BCM4359C0","BCM4359C0"},	//AP6398s
184*4882a593Smuzhiyun 	{(char *) NULL, NULL}
185*4882a593Smuzhiyun };
186*4882a593Smuzhiyun int uart_fd = -1;
187*4882a593Smuzhiyun int hcdfile_fd = -1;
188*4882a593Smuzhiyun int termios_baudrate = 0;
189*4882a593Smuzhiyun int bdaddr_flag = 0;
190*4882a593Smuzhiyun int enable_lpm = 0;
191*4882a593Smuzhiyun int enable_hci = 0;
192*4882a593Smuzhiyun int use_baudrate_for_download = 0;
193*4882a593Smuzhiyun int debug = 0;
194*4882a593Smuzhiyun int scopcm = 0;
195*4882a593Smuzhiyun int i2s = 0;
196*4882a593Smuzhiyun int no2bytes = 0;
197*4882a593Smuzhiyun int tosleep = 0;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun struct termios termios;
200*4882a593Smuzhiyun uchar buffer[1024];
201*4882a593Smuzhiyun uchar local_name[LOCAL_NAME_BUFFER_LEN];
202*4882a593Smuzhiyun uchar fw_folder_path[1024];
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun uchar hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun uchar hci_read_local_name[] = { 0x01, 0x14, 0x0c, 0x00 };
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun uchar hci_download_minidriver[] = { 0x01, 0x2e, 0xfc, 0x00 };
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun uchar hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00,
211*4882a593Smuzhiyun 	0x00, 0x00, 0x00, 0x00 };
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun uchar hci_write_bd_addr[] = { 0x01, 0x01, 0xfc, 0x06,
214*4882a593Smuzhiyun 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun uchar hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc, 0x0c,
217*4882a593Smuzhiyun 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
218*4882a593Smuzhiyun 	0x00, 0x00 };
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun uchar hci_write_sco_pcm_int[] =
221*4882a593Smuzhiyun 	{ 0x01, 0x1C, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun uchar hci_write_pcm_data_format[] =
224*4882a593Smuzhiyun 	{ 0x01, 0x1e, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun uchar hci_write_i2spcm_interface_param[] =
227*4882a593Smuzhiyun 	{ 0x01, 0x6d, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00 };
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun int
parse_patchram(char * optarg)230*4882a593Smuzhiyun parse_patchram(char *optarg)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	int len = strlen(optarg);
233*4882a593Smuzhiyun 	char *p = optarg+len-1;;
234*4882a593Smuzhiyun 	/*Look for first '/' to know the fw path*/
235*4882a593Smuzhiyun 	while(len>0)
236*4882a593Smuzhiyun 	{
237*4882a593Smuzhiyun 		if(*p == '/')
238*4882a593Smuzhiyun 			break;
239*4882a593Smuzhiyun 		len--;
240*4882a593Smuzhiyun 		p--;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 	if(len>0)
243*4882a593Smuzhiyun 	{
244*4882a593Smuzhiyun 		*p =0;
245*4882a593Smuzhiyun 		strcpy(fw_folder_path,optarg);
246*4882a593Smuzhiyun 		fprintf(stderr,"FW folder path = %s\n", fw_folder_path);
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun #if 0
249*4882a593Smuzhiyun 	char *p;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	if (!(p = strrchr(optarg, '.'))) {
252*4882a593Smuzhiyun 		fprintf(stderr, "file %s not an HCD file\n", optarg);
253*4882a593Smuzhiyun 		exit(3);
254*4882a593Smuzhiyun 	}
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	p++;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	if (strcasecmp("hcd", p) != 0) {
259*4882a593Smuzhiyun 		fprintf(stderr, "file %s not an HCD file\n", optarg);
260*4882a593Smuzhiyun 		exit(4);
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	if ((hcdfile_fd = open(optarg, O_RDONLY)) == -1) {
264*4882a593Smuzhiyun 		fprintf(stderr, "file %s could not be opened, error %d\n", optarg, errno);
265*4882a593Smuzhiyun 		exit(5);
266*4882a593Smuzhiyun 	}
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun #endif
269*4882a593Smuzhiyun 	return(0);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun void
BRCM_encode_baud_rate(uint baud_rate,uchar * encoded_baud)273*4882a593Smuzhiyun BRCM_encode_baud_rate(uint baud_rate, uchar *encoded_baud)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	if(baud_rate == 0 || encoded_baud == NULL) {
276*4882a593Smuzhiyun 		fprintf(stderr, "Baudrate not supported!");
277*4882a593Smuzhiyun 		return;
278*4882a593Smuzhiyun 	}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	encoded_baud[3] = (uchar)(baud_rate >> 24);
281*4882a593Smuzhiyun 	encoded_baud[2] = (uchar)(baud_rate >> 16);
282*4882a593Smuzhiyun 	encoded_baud[1] = (uchar)(baud_rate >> 8);
283*4882a593Smuzhiyun 	encoded_baud[0] = (uchar)(baud_rate & 0xFF);
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun typedef struct {
287*4882a593Smuzhiyun 	int baud_rate;
288*4882a593Smuzhiyun 	int termios_value;
289*4882a593Smuzhiyun } tBaudRates;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun tBaudRates baud_rates[] = {
292*4882a593Smuzhiyun 	{ 115200, B115200 },
293*4882a593Smuzhiyun 	{ 230400, B230400 },
294*4882a593Smuzhiyun 	{ 460800, B460800 },
295*4882a593Smuzhiyun 	{ 500000, B500000 },
296*4882a593Smuzhiyun 	{ 576000, B576000 },
297*4882a593Smuzhiyun 	{ 921600, B921600 },
298*4882a593Smuzhiyun 	{ 1000000, B1000000 },
299*4882a593Smuzhiyun 	{ 1152000, B1152000 },
300*4882a593Smuzhiyun 	{ 1500000, B1500000 },
301*4882a593Smuzhiyun 	{ 2000000, B2000000 },
302*4882a593Smuzhiyun 	{ 2500000, B2500000 },
303*4882a593Smuzhiyun 	{ 3000000, B3000000 },
304*4882a593Smuzhiyun #ifndef __CYGWIN__
305*4882a593Smuzhiyun 	{ 3500000, B3500000 },
306*4882a593Smuzhiyun 	{ 4000000, B4000000 }
307*4882a593Smuzhiyun #endif
308*4882a593Smuzhiyun };
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun int
validate_baudrate(int baud_rate,int * value)311*4882a593Smuzhiyun validate_baudrate(int baud_rate, int *value)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	unsigned int i;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	for (i = 0; i < (sizeof(baud_rates) / sizeof(tBaudRates)); i++) {
316*4882a593Smuzhiyun 		if (baud_rates[i].baud_rate == baud_rate) {
317*4882a593Smuzhiyun 			*value = baud_rates[i].termios_value;
318*4882a593Smuzhiyun 			return(1);
319*4882a593Smuzhiyun 		}
320*4882a593Smuzhiyun 	}
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	return(0);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun int
parse_baudrate(char * optarg)326*4882a593Smuzhiyun parse_baudrate(char *optarg)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun 	int baudrate = atoi(optarg);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (validate_baudrate(baudrate, &termios_baudrate)) {
331*4882a593Smuzhiyun 		BRCM_encode_baud_rate(baudrate, &hci_update_baud_rate[6]);
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	return(0);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun int
parse_bdaddr(char * optarg)338*4882a593Smuzhiyun parse_bdaddr(char *optarg)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	int bd_addr[6];
341*4882a593Smuzhiyun 	int i;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X",
344*4882a593Smuzhiyun 		&bd_addr[5], &bd_addr[4], &bd_addr[3],
345*4882a593Smuzhiyun 		&bd_addr[2], &bd_addr[1], &bd_addr[0]);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	for (i = 0; i < 6; i++) {
348*4882a593Smuzhiyun 		hci_write_bd_addr[4 + i] = bd_addr[i];
349*4882a593Smuzhiyun 	}
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	bdaddr_flag = 1;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	return(0);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun int
readApName(char * name,int len)357*4882a593Smuzhiyun readApName(char *name, int len)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	FILE* devInfo = NULL;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun     if(len < AP_NAME_SUFFIX_LEN) {
362*4882a593Smuzhiyun         return -1;
363*4882a593Smuzhiyun     }
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun     devInfo = fopen("/data/cfg/device_info.txt","rb+");
366*4882a593Smuzhiyun     if(devInfo) {
367*4882a593Smuzhiyun         fseek(devInfo, 36, SEEK_SET);
368*4882a593Smuzhiyun         fread(name, 1, AP_NAME_SUFFIX_LEN, devInfo);
369*4882a593Smuzhiyun         fclose(devInfo);
370*4882a593Smuzhiyun         // is default value or not
371*4882a593Smuzhiyun         if(0 == strncmp(name, "11:22:33:44:55:66", 17)) {
372*4882a593Smuzhiyun             return -1;
373*4882a593Smuzhiyun         }
374*4882a593Smuzhiyun     } else {
375*4882a593Smuzhiyun         return -1;
376*4882a593Smuzhiyun     }
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun     return 0;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun int
writeApName(const char * name,int len)382*4882a593Smuzhiyun writeApName(const char* name, int len)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun 	FILE* devInfo = NULL;
385*4882a593Smuzhiyun     char nameBuf[AP_NAME_SUFFIX_LEN] = {0};
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun     if(len < 17) {
388*4882a593Smuzhiyun         return -1;
389*4882a593Smuzhiyun     }
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     if(0 != strncmp(name, "11:22:33:44:55", 17)) {
392*4882a593Smuzhiyun         devInfo = fopen("/data/cfg/device_info.txt","rb+");
393*4882a593Smuzhiyun         if(devInfo) {
394*4882a593Smuzhiyun             fseek(devInfo, 36, SEEK_SET);
395*4882a593Smuzhiyun             snprintf(nameBuf, AP_NAME_SUFFIX_LEN, "%s", name);
396*4882a593Smuzhiyun             fwrite(nameBuf, 1, AP_NAME_SUFFIX_LEN, devInfo);
397*4882a593Smuzhiyun             fflush(devInfo);
398*4882a593Smuzhiyun             fsync(fileno(devInfo));
399*4882a593Smuzhiyun             fclose(devInfo);
400*4882a593Smuzhiyun         }
401*4882a593Smuzhiyun         system("cp /data/cfg/device_info.txt /data/cfg/device_info");
402*4882a593Smuzhiyun     }
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun int
parse_bdaddr_rand(char * optarg)406*4882a593Smuzhiyun parse_bdaddr_rand(char *optarg)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	int bd_addr[6];
409*4882a593Smuzhiyun 	int i,j;
410*4882a593Smuzhiyun 	char optargtest[18];
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	char mh[]=":";
413*4882a593Smuzhiyun 	char metachar[]="ABCDEF0123456789";
414*4882a593Smuzhiyun 	if(0 != readApName(optargtest,AP_NAME_SUFFIX_LEN)){
415*4882a593Smuzhiyun 		srand(time(NULL));
416*4882a593Smuzhiyun 		for(j=0;j<17;j++){
417*4882a593Smuzhiyun 			if(j%3 == 2){
418*4882a593Smuzhiyun 			optargtest[j]= mh[0];
419*4882a593Smuzhiyun 			}else{
420*4882a593Smuzhiyun 				optargtest[j] = metachar[rand()%16];
421*4882a593Smuzhiyun 			}
422*4882a593Smuzhiyun 		}
423*4882a593Smuzhiyun 		optargtest[17]='\0';
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 		writeApName(optargtest,AP_NAME_SUFFIX_LEN);
426*4882a593Smuzhiyun 	}
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	sscanf(optargtest, "%02X:%02X:%02X:%02X:%02X:%02X",
429*4882a593Smuzhiyun 		&bd_addr[5], &bd_addr[4], &bd_addr[3],
430*4882a593Smuzhiyun 		&bd_addr[2], &bd_addr[1], &bd_addr[0]);
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	for (i = 0; i < 6; i++) {
433*4882a593Smuzhiyun 		hci_write_bd_addr[4 + i] = bd_addr[i];
434*4882a593Smuzhiyun 	}
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	bdaddr_flag = 1;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	return(0);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun int
parse_enable_lpm(char * optarg)442*4882a593Smuzhiyun parse_enable_lpm(char *optarg)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun 	enable_lpm = 1;
445*4882a593Smuzhiyun 	return(0);
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun int
parse_use_baudrate_for_download(char * optarg)449*4882a593Smuzhiyun parse_use_baudrate_for_download(char *optarg)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun 	use_baudrate_for_download = 1;
452*4882a593Smuzhiyun 	return(0);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun int
parse_enable_hci(char * optarg)456*4882a593Smuzhiyun parse_enable_hci(char *optarg)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	enable_hci = 1;
459*4882a593Smuzhiyun 	return(0);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun int
parse_scopcm(char * optarg)463*4882a593Smuzhiyun parse_scopcm(char *optarg)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun 	int param[10];
466*4882a593Smuzhiyun 	int ret;
467*4882a593Smuzhiyun 	int i;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	ret = sscanf(optarg, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
470*4882a593Smuzhiyun 		&param[0], &param[1], &param[2], &param[3], &param[4],
471*4882a593Smuzhiyun 		&param[5], &param[6], &param[7], &param[8], &param[9]);
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	if (ret != 10) {
474*4882a593Smuzhiyun 		return(1);
475*4882a593Smuzhiyun 	}
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	scopcm = 1;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	for (i = 0; i < 5; i++) {
480*4882a593Smuzhiyun 		hci_write_sco_pcm_int[4 + i] = param[i];
481*4882a593Smuzhiyun 	}
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	for (i = 0; i < 5; i++) {
484*4882a593Smuzhiyun 		hci_write_pcm_data_format[4 + i] = param[5 + i];
485*4882a593Smuzhiyun 	}
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	return(0);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun int
parse_i2s(char * optarg)491*4882a593Smuzhiyun parse_i2s(char *optarg)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun 	int param[4];
494*4882a593Smuzhiyun 	int ret;
495*4882a593Smuzhiyun 	int i;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	ret = sscanf(optarg, "%d,%d,%d,%d", &param[0], &param[1], &param[2],
498*4882a593Smuzhiyun 		&param[3]);
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	if (ret != 4) {
501*4882a593Smuzhiyun 		return(1);
502*4882a593Smuzhiyun 	}
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	i2s = 1;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
507*4882a593Smuzhiyun 		hci_write_i2spcm_interface_param[4 + i] = param[i];
508*4882a593Smuzhiyun 	}
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	return(0);
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun int
parse_no2bytes(char * optarg)514*4882a593Smuzhiyun parse_no2bytes(char *optarg)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun 	no2bytes = 1;
517*4882a593Smuzhiyun 	return(0);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun int
parse_tosleep(char * optarg)521*4882a593Smuzhiyun parse_tosleep(char *optarg)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	tosleep = atoi(optarg);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	if (tosleep <= 0) {
526*4882a593Smuzhiyun 		return(1);
527*4882a593Smuzhiyun 	}
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	return(0);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun void
usage(char * argv0)533*4882a593Smuzhiyun usage(char *argv0)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun 	printf("Usage %s:\n", argv0);
536*4882a593Smuzhiyun 	printf("\t<-d> to print a debug log\n");
537*4882a593Smuzhiyun 	printf("\t<--patchram patchram_file>\n");
538*4882a593Smuzhiyun 	printf("\t<--baudrate baud_rate>\n");
539*4882a593Smuzhiyun 	printf("\t<--bd_addr bd_address>\n");
540*4882a593Smuzhiyun 	printf("\t<--enable_lpm>\n");
541*4882a593Smuzhiyun 	printf("\t<--enable_hci>\n");
542*4882a593Smuzhiyun 	printf("\t<--use_baudrate_for_download> - Uses the\n");
543*4882a593Smuzhiyun 	printf("\t\tbaudrate for downloading the firmware\n");
544*4882a593Smuzhiyun 	printf("\t<--scopcm=sco_routing,pcm_interface_rate,frame_type,\n");
545*4882a593Smuzhiyun 	printf("\t\tsync_mode,clock_mode,lsb_first,fill_bits,\n");
546*4882a593Smuzhiyun 	printf("\t\tfill_method,fill_num,right_justify>\n");
547*4882a593Smuzhiyun 	printf("\n\t\tWhere\n");
548*4882a593Smuzhiyun 	printf("\n\t\tsco_routing is 0 for PCM, 1 for Transport,\n");
549*4882a593Smuzhiyun 	printf("\t\t2 for Codec and 3 for I2S,\n");
550*4882a593Smuzhiyun 	printf("\n\t\tpcm_interface_rate is 0 for 128KBps, 1 for\n");
551*4882a593Smuzhiyun 	printf("\t\t256 KBps, 2 for 512KBps, 3 for 1024KBps,\n");
552*4882a593Smuzhiyun 	printf("\t\tand 4 for 2048Kbps,\n");
553*4882a593Smuzhiyun 	printf("\n\t\tframe_type is 0 for short and 1 for long,\n");
554*4882a593Smuzhiyun 	printf("\t\tsync_mode is 0 for slave and 1 for master,\n");
555*4882a593Smuzhiyun 	printf("\n\t\tclock_mode is 0 for slabe and 1 for master,\n");
556*4882a593Smuzhiyun 	printf("\n\t\tlsb_first is 0 for false aand 1 for true,\n");
557*4882a593Smuzhiyun 	printf("\n\t\tfill_bits is the value in decimal for unused bits,\n");
558*4882a593Smuzhiyun 	printf("\n\t\tfill_method is 0 for 0's and 1 for 1's, 2 for\n");
559*4882a593Smuzhiyun 	printf("\t\tsigned and 3 for programmable,\n");
560*4882a593Smuzhiyun 	printf("\n\t\tfill_num is the number or bits to fill,\n");
561*4882a593Smuzhiyun 	printf("\n\t\tright_justify is 0 for false and 1 for true\n");
562*4882a593Smuzhiyun 	printf("\n\t<--i2s=i2s_enable,is_master,sample_rate,clock_rate>\n");
563*4882a593Smuzhiyun 	printf("\n\t\tWhere\n");
564*4882a593Smuzhiyun 	printf("\n\t\ti2s_enable is 0 for disable and 1 for enable,\n");
565*4882a593Smuzhiyun 	printf("\n\t\tis_master is 0 for slave and 1 for master,\n");
566*4882a593Smuzhiyun 	printf("\n\t\tsample_rate is 0 for 8KHz, 1 for 16Khz and\n");
567*4882a593Smuzhiyun 	printf("\t\t2 for 4 KHz,\n");
568*4882a593Smuzhiyun 	printf("\n\t\tclock_rate is 0 for 128KHz, 1 for 256KHz, 3 for\n");
569*4882a593Smuzhiyun 	printf("\t\t1024 KHz and 4 for 2048 KHz.\n\n");
570*4882a593Smuzhiyun 	printf("\t<--no2bytes skips waiting for two byte confirmation\n");
571*4882a593Smuzhiyun 	printf("\t\tbefore starting patchram download. Newer chips\n");
572*4882a593Smuzhiyun 	printf("\t\tdo not generate these two bytes.>\n");
573*4882a593Smuzhiyun 	printf("\t<--tosleep=microseconds>\n");
574*4882a593Smuzhiyun 	printf("\tuart_device_name\n");
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun int
parse_cmd_line(int argc,char ** argv)578*4882a593Smuzhiyun parse_cmd_line(int argc, char **argv)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun 	int c;
581*4882a593Smuzhiyun 	int ret = 0;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	typedef int (*PFI)();
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	PFI parse[] = { parse_patchram, parse_baudrate,
586*4882a593Smuzhiyun 		parse_bdaddr,parse_bdaddr_rand, parse_enable_lpm, parse_enable_hci,
587*4882a593Smuzhiyun 		parse_use_baudrate_for_download,
588*4882a593Smuzhiyun 		parse_scopcm, parse_i2s, parse_no2bytes, parse_tosleep};
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	while (1) {
591*4882a593Smuzhiyun 		int this_option_optind = optind ? optind : 1;
592*4882a593Smuzhiyun 		int option_index = 0;
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 		static struct option long_options[] = {
595*4882a593Smuzhiyun 			{"patchram", 1, 0, 0},
596*4882a593Smuzhiyun 			{"baudrate", 1, 0, 0},
597*4882a593Smuzhiyun 			{"bd_addr", 1, 0, 0},
598*4882a593Smuzhiyun 			{"bd_addr_rand", 0, 0, 0},
599*4882a593Smuzhiyun 			{"enable_lpm", 0, 0, 0},
600*4882a593Smuzhiyun 			{"enable_hci", 0, 0, 0},
601*4882a593Smuzhiyun 			{"use_baudrate_for_download", 0, 0, 0},
602*4882a593Smuzhiyun 			{"scopcm", 1, 0, 0},
603*4882a593Smuzhiyun 			{"i2s", 1, 0, 0},
604*4882a593Smuzhiyun 			{"no2bytes", 0, 0, 0},
605*4882a593Smuzhiyun 			{"tosleep", 1, 0, 0},
606*4882a593Smuzhiyun 			{0, 0, 0, 0}
607*4882a593Smuzhiyun 		};
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 		c = getopt_long_only (argc, argv, "d", long_options,
610*4882a593Smuzhiyun 				&option_index);
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 		if (c == -1) {
613*4882a593Smuzhiyun 			break;
614*4882a593Smuzhiyun 		}
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 		switch (c) {
617*4882a593Smuzhiyun 			case 0:
618*4882a593Smuzhiyun 				if (debug) {
619*4882a593Smuzhiyun 					printf ("option %s",
620*4882a593Smuzhiyun 						long_options[option_index].name);
621*4882a593Smuzhiyun 					if (optarg)
622*4882a593Smuzhiyun 						printf (" with arg %s", optarg);
623*4882a593Smuzhiyun 					printf ("\n");
624*4882a593Smuzhiyun 				}
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 				ret = (*parse[option_index])(optarg);
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 				break;
629*4882a593Smuzhiyun 			case 'd':
630*4882a593Smuzhiyun 				debug = 1;
631*4882a593Smuzhiyun 				break;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 			case '?':
634*4882a593Smuzhiyun 				//nobreak
635*4882a593Smuzhiyun 			default:
636*4882a593Smuzhiyun 				usage(argv[0]);
637*4882a593Smuzhiyun 				break;
638*4882a593Smuzhiyun 		}
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 		if (ret) {
641*4882a593Smuzhiyun 			usage(argv[0]);
642*4882a593Smuzhiyun 			break;
643*4882a593Smuzhiyun 		}
644*4882a593Smuzhiyun 	}
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	if (ret) {
647*4882a593Smuzhiyun 		return(1);
648*4882a593Smuzhiyun 	}
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	if (optind < argc) {
651*4882a593Smuzhiyun 		if (debug)
652*4882a593Smuzhiyun 			printf ("%s \n", argv[optind]);
653*4882a593Smuzhiyun 		if ((uart_fd = open(argv[optind], O_RDWR | O_NOCTTY)) == -1) {
654*4882a593Smuzhiyun 			fprintf(stderr, "port %s could not be opened, error %d\n",
655*4882a593Smuzhiyun 					argv[2], errno);
656*4882a593Smuzhiyun 		}
657*4882a593Smuzhiyun 	}
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	return(0);
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun void
init_uart()663*4882a593Smuzhiyun init_uart()
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun 	tcflush(uart_fd, TCIOFLUSH);
666*4882a593Smuzhiyun 	tcgetattr(uart_fd, &termios);
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun #ifndef __CYGWIN__
669*4882a593Smuzhiyun 	cfmakeraw(&termios);
670*4882a593Smuzhiyun #else
671*4882a593Smuzhiyun 	termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
672*4882a593Smuzhiyun                 | INLCR | IGNCR | ICRNL | IXON);
673*4882a593Smuzhiyun 	termios.c_oflag &= ~OPOST;
674*4882a593Smuzhiyun 	termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
675*4882a593Smuzhiyun 	termios.c_cflag &= ~(CSIZE | PARENB);
676*4882a593Smuzhiyun 	termios.c_cflag |= CS8;
677*4882a593Smuzhiyun #endif
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 	termios.c_cflag |= CRTSCTS;
680*4882a593Smuzhiyun 	tcsetattr(uart_fd, TCSANOW, &termios);
681*4882a593Smuzhiyun 	tcflush(uart_fd, TCIOFLUSH);
682*4882a593Smuzhiyun 	tcsetattr(uart_fd, TCSANOW, &termios);
683*4882a593Smuzhiyun 	tcflush(uart_fd, TCIOFLUSH);
684*4882a593Smuzhiyun 	tcflush(uart_fd, TCIOFLUSH);
685*4882a593Smuzhiyun 	cfsetospeed(&termios, B115200);
686*4882a593Smuzhiyun 	cfsetispeed(&termios, B115200);
687*4882a593Smuzhiyun 	tcsetattr(uart_fd, TCSANOW, &termios);
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun void
dump(uchar * out,int len)691*4882a593Smuzhiyun dump(uchar *out, int len)
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun 	int i;
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
696*4882a593Smuzhiyun 		if (i && !(i % 16)) {
697*4882a593Smuzhiyun 			fprintf(stderr, "\n");
698*4882a593Smuzhiyun 		}
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 		fprintf(stderr, "%02x ", out[i]);
701*4882a593Smuzhiyun 	}
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	fprintf(stderr, "\n");
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun void
read_event(int fd,uchar * buffer)707*4882a593Smuzhiyun read_event(int fd, uchar *buffer)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun 	int i = 0;
710*4882a593Smuzhiyun 	int len = 3;
711*4882a593Smuzhiyun 	int count;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	while ((count = read(fd, &buffer[i], len)) < len) {
714*4882a593Smuzhiyun 		i += count;
715*4882a593Smuzhiyun 		len -= count;
716*4882a593Smuzhiyun 		//fprintf(stderr, "received11 %d\n", count);
717*4882a593Smuzhiyun 	}
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	i += count;
720*4882a593Smuzhiyun 	len = buffer[2];
721*4882a593Smuzhiyun 	//fprintf(stderr, "received22 %d\n", count);
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	while ((count = read(fd, &buffer[i], len)) < len) {
724*4882a593Smuzhiyun 		i += count;
725*4882a593Smuzhiyun 		len -= count;
726*4882a593Smuzhiyun 	}
727*4882a593Smuzhiyun 	//fprintf(stderr, "received33 %d\n", count);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	if (debug) {
730*4882a593Smuzhiyun 		count += i;
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 		fprintf(stderr, "received %d\n", count);
733*4882a593Smuzhiyun 		dump(buffer, count);
734*4882a593Smuzhiyun 	}
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun void
hci_send_cmd(uchar * buf,int len)738*4882a593Smuzhiyun hci_send_cmd(uchar *buf, int len)
739*4882a593Smuzhiyun {
740*4882a593Smuzhiyun 	if (debug) {
741*4882a593Smuzhiyun 		fprintf(stderr, "writing\n");
742*4882a593Smuzhiyun 		dump(buf, len);
743*4882a593Smuzhiyun 	}
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	write(uart_fd, buf, len);
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun void
expired(int sig)749*4882a593Smuzhiyun expired(int sig)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun 	hci_send_cmd(hci_reset, sizeof(hci_reset));
752*4882a593Smuzhiyun 	alarm(4);
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun void
proc_reset()756*4882a593Smuzhiyun proc_reset()
757*4882a593Smuzhiyun {
758*4882a593Smuzhiyun 	signal(SIGALRM, expired);
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 	fprintf(stderr, "proc_reset");
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	hci_send_cmd(hci_reset, sizeof(hci_reset));
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	alarm(4);
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	alarm(0);
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun void
proc_read_local_name()772*4882a593Smuzhiyun proc_read_local_name()
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun 	int i;
775*4882a593Smuzhiyun 	char *p_name;
776*4882a593Smuzhiyun 	hci_send_cmd(hci_read_local_name, sizeof(hci_read_local_name));
777*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
778*4882a593Smuzhiyun 	p_name = &buffer[1+HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING];
779*4882a593Smuzhiyun 	for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++)
780*4882a593Smuzhiyun 		*(p_name+i) = toupper(*(p_name+i));
781*4882a593Smuzhiyun 	strcpy(local_name,p_name);
782*4882a593Smuzhiyun 	fprintf(stderr,"chip id = %s\n", local_name);
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun void
proc_open_patchram()786*4882a593Smuzhiyun proc_open_patchram()
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun 	char fw_path[1024];
789*4882a593Smuzhiyun 	char *p;
790*4882a593Smuzhiyun 	int i;
791*4882a593Smuzhiyun 	fw_auto_detection_entry_t *p_entry;
792*4882a593Smuzhiyun 	p_entry = (fw_auto_detection_entry_t *)fw_auto_detection_table;
793*4882a593Smuzhiyun 	while (p_entry->chip_id != NULL)
794*4882a593Smuzhiyun 	{
795*4882a593Smuzhiyun 		if (strstr(local_name, p_entry->chip_id)!=NULL)
796*4882a593Smuzhiyun 		{
797*4882a593Smuzhiyun 			strcpy(local_name,p_entry->updated_chip_id);
798*4882a593Smuzhiyun 			break;
799*4882a593Smuzhiyun 		}
800*4882a593Smuzhiyun 		p_entry++;
801*4882a593Smuzhiyun 	}
802*4882a593Smuzhiyun 	sprintf(fw_path,"%s/%s.hcd",fw_folder_path,local_name);
803*4882a593Smuzhiyun 	fprintf(stderr, "FW path = %s\n", fw_path);
804*4882a593Smuzhiyun 	if ((hcdfile_fd = open(fw_path, O_RDONLY)) == -1) {
805*4882a593Smuzhiyun 		fprintf(stderr, "file %s could not be opened, error %d\n", fw_path , errno);
806*4882a593Smuzhiyun 		p = local_name;
807*4882a593Smuzhiyun 		fprintf(stderr, "Retry lower case FW name\n");
808*4882a593Smuzhiyun 		for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p+i) != 0); i++)
809*4882a593Smuzhiyun 			*(p+i) = tolower(*(p+i));
810*4882a593Smuzhiyun 		sprintf(fw_path,"%s/%s.hcd",fw_folder_path,local_name);
811*4882a593Smuzhiyun 		fprintf(stderr, "FW path = %s\n", fw_path);
812*4882a593Smuzhiyun 		if ((hcdfile_fd = open(fw_path, O_RDONLY)) == -1) {
813*4882a593Smuzhiyun 			fprintf(stderr, "file %s could not be opened, error %d\n", fw_path, errno);
814*4882a593Smuzhiyun 			exit(5);
815*4882a593Smuzhiyun 		}
816*4882a593Smuzhiyun 	}
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun void
proc_patchram()820*4882a593Smuzhiyun proc_patchram()
821*4882a593Smuzhiyun {
822*4882a593Smuzhiyun 	int len;
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 	hci_send_cmd(hci_download_minidriver, sizeof(hci_download_minidriver));
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 	fprintf(stderr, "send hci_download_minidriver");
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	if (!no2bytes) {
831*4882a593Smuzhiyun 		read(uart_fd, &buffer[0], 2);
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	if (tosleep) {
835*4882a593Smuzhiyun 		usleep(tosleep);
836*4882a593Smuzhiyun 	}
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	while (read(hcdfile_fd, &buffer[1], 3)) {
839*4882a593Smuzhiyun 		buffer[0] = 0x01;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 		len = buffer[3];
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 		read(hcdfile_fd, &buffer[4], len);
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 		hci_send_cmd(buffer, len + 4);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 		read_event(uart_fd, buffer);
848*4882a593Smuzhiyun 	}
849*4882a593Smuzhiyun 	usleep(200000);
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	if (use_baudrate_for_download) {
852*4882a593Smuzhiyun 		cfsetospeed(&termios, B115200);
853*4882a593Smuzhiyun 		cfsetispeed(&termios, B115200);
854*4882a593Smuzhiyun 		tcsetattr(uart_fd, TCSANOW, &termios);
855*4882a593Smuzhiyun 	}
856*4882a593Smuzhiyun 	proc_reset();
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun void
proc_baudrate()860*4882a593Smuzhiyun proc_baudrate()
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun 	hci_send_cmd(hci_update_baud_rate, sizeof(hci_update_baud_rate));
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	usleep(200000);
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	cfsetospeed(&termios, termios_baudrate);
869*4882a593Smuzhiyun 	cfsetispeed(&termios, termios_baudrate);
870*4882a593Smuzhiyun 	tcsetattr(uart_fd, TCSANOW, &termios);
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	if (debug) {
873*4882a593Smuzhiyun 		fprintf(stderr, "Done setting baudrate\n");
874*4882a593Smuzhiyun 	}
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun void
proc_bdaddr()878*4882a593Smuzhiyun proc_bdaddr()
879*4882a593Smuzhiyun {
880*4882a593Smuzhiyun 	hci_send_cmd(hci_write_bd_addr, sizeof(hci_write_bd_addr));
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun void
proc_enable_lpm()886*4882a593Smuzhiyun proc_enable_lpm()
887*4882a593Smuzhiyun {
888*4882a593Smuzhiyun 	hci_send_cmd(hci_write_sleep_mode, sizeof(hci_write_sleep_mode));
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun void
proc_scopcm()894*4882a593Smuzhiyun proc_scopcm()
895*4882a593Smuzhiyun {
896*4882a593Smuzhiyun 	hci_send_cmd(hci_write_sco_pcm_int,
897*4882a593Smuzhiyun 		sizeof(hci_write_sco_pcm_int));
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun 	hci_send_cmd(hci_write_pcm_data_format,
902*4882a593Smuzhiyun 		sizeof(hci_write_pcm_data_format));
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
905*4882a593Smuzhiyun }
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun void
proc_i2s()908*4882a593Smuzhiyun proc_i2s()
909*4882a593Smuzhiyun {
910*4882a593Smuzhiyun 	hci_send_cmd(hci_write_i2spcm_interface_param,
911*4882a593Smuzhiyun 		sizeof(hci_write_i2spcm_interface_param));
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	read_event(uart_fd, buffer);
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun void
proc_enable_hci()917*4882a593Smuzhiyun proc_enable_hci()
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun 	int i = N_HCI;
920*4882a593Smuzhiyun 	int proto = HCI_UART_H4;
921*4882a593Smuzhiyun 	if (ioctl(uart_fd, TIOCSETD, &i) < 0) {
922*4882a593Smuzhiyun 		fprintf(stderr, "Can't set line discipline\n");
923*4882a593Smuzhiyun 		return;
924*4882a593Smuzhiyun 	}
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun 	if (ioctl(uart_fd, HCIUARTSETPROTO, proto) < 0) {
927*4882a593Smuzhiyun 		fprintf(stderr, "Can't set hci protocol\n");
928*4882a593Smuzhiyun 		return;
929*4882a593Smuzhiyun 	}
930*4882a593Smuzhiyun 	fprintf(stderr, "Done setting line discpline\n");
931*4882a593Smuzhiyun 	return;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun #ifdef ANDROID
935*4882a593Smuzhiyun void
read_default_bdaddr()936*4882a593Smuzhiyun read_default_bdaddr()
937*4882a593Smuzhiyun {
938*4882a593Smuzhiyun 	int sz;
939*4882a593Smuzhiyun 	int fd;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	char path[PROPERTY_VALUE_MAX];
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	char bdaddr[18];
944*4882a593Smuzhiyun 	int len = 17;
945*4882a593Smuzhiyun 	memset(bdaddr, 0, (len + 1) * sizeof(char));
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun 	property_get("ro.bt.bdaddr_path", path, "");
948*4882a593Smuzhiyun 	if (path[0] == 0)
949*4882a593Smuzhiyun 		return;
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun 	fd = open(path, O_RDONLY);
952*4882a593Smuzhiyun 	if (fd < 0) {
953*4882a593Smuzhiyun 		fprintf(stderr, "open(%s) failed: %s (%d)", path, strerror(errno),
954*4882a593Smuzhiyun 				errno);
955*4882a593Smuzhiyun 		return;
956*4882a593Smuzhiyun 	}
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	sz = read(fd, bdaddr, len);
959*4882a593Smuzhiyun 	if (sz < 0) {
960*4882a593Smuzhiyun 		fprintf(stderr, "read(%s) failed: %s (%d)", path, strerror(errno),
961*4882a593Smuzhiyun 				errno);
962*4882a593Smuzhiyun 		close(fd);
963*4882a593Smuzhiyun 		return;
964*4882a593Smuzhiyun 	} else if (sz != len) {
965*4882a593Smuzhiyun 		fprintf(stderr, "read(%s) unexpected size %d", path, sz);
966*4882a593Smuzhiyun 		close(fd);
967*4882a593Smuzhiyun 		return;
968*4882a593Smuzhiyun 	}
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun 	if (debug) {
971*4882a593Smuzhiyun 		printf("Read default bdaddr of %s\n", bdaddr);
972*4882a593Smuzhiyun 	}
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	parse_bdaddr(bdaddr);
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun #endif
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun int
main(int argc,char ** argv)980*4882a593Smuzhiyun main (int argc, char **argv)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun #ifdef ANDROID
983*4882a593Smuzhiyun 	read_default_bdaddr();
984*4882a593Smuzhiyun #endif
985*4882a593Smuzhiyun 	fprintf(stderr, "###AMPAK FW Auto detection patch version = [%s]###\n", FW_TABLE_VERSION);
986*4882a593Smuzhiyun 	if (parse_cmd_line(argc, argv)) {
987*4882a593Smuzhiyun 		exit(1);
988*4882a593Smuzhiyun 	}
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 	if (uart_fd < 0) {
991*4882a593Smuzhiyun 		exit(2);
992*4882a593Smuzhiyun 	}
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 	init_uart();
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	proc_reset();
997*4882a593Smuzhiyun 	proc_read_local_name();
998*4882a593Smuzhiyun 	proc_open_patchram();
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	if (use_baudrate_for_download) {
1001*4882a593Smuzhiyun 		if (termios_baudrate) {
1002*4882a593Smuzhiyun 			proc_baudrate();
1003*4882a593Smuzhiyun 		}
1004*4882a593Smuzhiyun 	}
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	if (hcdfile_fd > 0) {
1007*4882a593Smuzhiyun 		proc_patchram();
1008*4882a593Smuzhiyun 	}
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	if (termios_baudrate) {
1011*4882a593Smuzhiyun 		proc_baudrate();
1012*4882a593Smuzhiyun 	}
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	if (bdaddr_flag) {
1015*4882a593Smuzhiyun 		proc_bdaddr();
1016*4882a593Smuzhiyun 	}
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	if (enable_lpm) {
1019*4882a593Smuzhiyun 		proc_enable_lpm();
1020*4882a593Smuzhiyun 	}
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	if (scopcm) {
1023*4882a593Smuzhiyun 		proc_scopcm();
1024*4882a593Smuzhiyun 	}
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	if (i2s) {
1027*4882a593Smuzhiyun 		proc_i2s();
1028*4882a593Smuzhiyun 	}
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	if (enable_hci) {
1031*4882a593Smuzhiyun 		proc_enable_hci();
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 		while (1) {
1034*4882a593Smuzhiyun 			sleep(UINT_MAX);
1035*4882a593Smuzhiyun 		}
1036*4882a593Smuzhiyun 	}
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun 	exit(0);
1039*4882a593Smuzhiyun }
1040