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