xref: /OK3568_Linux_fs/yocto/meta-rockchip/recipes-devtools/brcm-tools/files/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 <stdio.h>
108 #include <getopt.h>
109 #include <errno.h>
110 
111 #include <sys/types.h>
112 #include <sys/stat.h>
113 #include <fcntl.h>
114 
115 #include <stdlib.h>
116 #include <time.h>
117 
118 #ifdef ANDROID
119 #include <termios.h>
120 #else
121 #include <sys/termios.h>
122 #include <sys/ioctl.h>
123 #include <limits.h>
124 #endif
125 
126 #include <string.h>
127 #include <signal.h>
128 
129 #ifdef ANDROID
130 #include <cutils/properties.h>
131 #define LOG_TAG "brcm_patchram_plus"
132 #include <cutils/log.h>
133 #undef printf
134 #define printf ALOGD
135 #undef fprintf
136 #define fprintf(x, ...) \
137   { if(x==stderr) ALOGE(__VA_ARGS__); else fprintf(x, __VA_ARGS__); }
138 
139 #endif //ANDROID
140 
141 #ifndef N_HCI
142 #define N_HCI	15
143 #endif
144 
145 #define HCIUARTSETPROTO		_IOW('U', 200, int)
146 #define HCIUARTGETPROTO		_IOR('U', 201, int)
147 #define HCIUARTGETDEVICE	_IOR('U', 202, int)
148 #define AP_NAME_SUFFIX_LEN 18
149 
150 #define HCI_UART_H4		0
151 #define HCI_UART_BCSP	1
152 #define HCI_UART_3WIRE	2
153 #define HCI_UART_H4DS	3
154 #define HCI_UART_LL		4
155 
156 typedef unsigned char uchar;
157 
158 int uart_fd = -1;
159 int hcdfile_fd = -1;
160 int termios_baudrate = 0;
161 int bdaddr_flag = 0;
162 int enable_lpm = 0;
163 int enable_hci = 0;
164 int use_baudrate_for_download = 0;
165 int debug = 0;
166 int scopcm = 0;
167 int i2s = 0;
168 int no2bytes = 0;
169 int tosleep = 0;
170 
171 struct termios termios;
172 uchar buffer[1024];
173 
174 uchar hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
175 
176 uchar hci_download_minidriver[] = { 0x01, 0x2e, 0xfc, 0x00 };
177 
178 uchar hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00,
179 	0x00, 0x00, 0x00, 0x00 };
180 
181 uchar hci_write_bd_addr[] = { 0x01, 0x01, 0xfc, 0x06,
182 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
183 
184 uchar hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc, 0x0c,
185 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
186 	0x00, 0x00 };
187 
188 uchar hci_write_sco_pcm_int[] =
189 	{ 0x01, 0x1C, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
190 
191 uchar hci_write_pcm_data_format[] =
192 	{ 0x01, 0x1e, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
193 
194 uchar hci_write_i2spcm_interface_param[] =
195 	{ 0x01, 0x6d, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00 };
196 
197 int
parse_patchram(char * optarg)198 parse_patchram(char *optarg)
199 {
200 	char *p;
201 
202 	if (!(p = strrchr(optarg, '.'))) {
203 		fprintf(stderr, "file %s not an HCD file\n", optarg);
204 		exit(3);
205 	}
206 
207 	p++;
208 
209 	if (strcasecmp("hcd", p) != 0) {
210 		fprintf(stderr, "file %s not an HCD file\n", optarg);
211 		exit(4);
212 	}
213 
214 	if ((hcdfile_fd = open(optarg, O_RDONLY)) == -1) {
215 		fprintf(stderr, "file %s could not be opened, error %d\n", optarg, errno);
216 		exit(5);
217 	}
218 
219 	return(0);
220 }
221 
222 void
BRCM_encode_baud_rate(uint baud_rate,uchar * encoded_baud)223 BRCM_encode_baud_rate(uint baud_rate, uchar *encoded_baud)
224 {
225 	if(baud_rate == 0 || encoded_baud == NULL) {
226 		fprintf(stderr, "Baudrate not supported!");
227 		return;
228 	}
229 
230 	encoded_baud[3] = (uchar)(baud_rate >> 24);
231 	encoded_baud[2] = (uchar)(baud_rate >> 16);
232 	encoded_baud[1] = (uchar)(baud_rate >> 8);
233 	encoded_baud[0] = (uchar)(baud_rate & 0xFF);
234 }
235 
236 typedef struct {
237 	int baud_rate;
238 	int termios_value;
239 } tBaudRates;
240 
241 tBaudRates baud_rates[] = {
242 	{ 115200, B115200 },
243 	{ 230400, B230400 },
244 	{ 460800, B460800 },
245 	{ 500000, B500000 },
246 	{ 576000, B576000 },
247 	{ 921600, B921600 },
248 	{ 1000000, B1000000 },
249 	{ 1152000, B1152000 },
250 	{ 1500000, B1500000 },
251 	{ 2000000, B2000000 },
252 	{ 2500000, B2500000 },
253 	{ 3000000, B3000000 },
254 #ifndef __CYGWIN__
255 	{ 3500000, B3500000 },
256 	{ 4000000, B4000000 }
257 #endif
258 };
259 
260 int
validate_baudrate(int baud_rate,int * value)261 validate_baudrate(int baud_rate, int *value)
262 {
263 	unsigned int i;
264 
265 	for (i = 0; i < (sizeof(baud_rates) / sizeof(tBaudRates)); i++) {
266 		if (baud_rates[i].baud_rate == baud_rate) {
267 			*value = baud_rates[i].termios_value;
268 			return(1);
269 		}
270 	}
271 
272 	return(0);
273 }
274 
275 int
parse_baudrate(char * optarg)276 parse_baudrate(char *optarg)
277 {
278 	int baudrate = atoi(optarg);
279 
280 	if (validate_baudrate(baudrate, &termios_baudrate)) {
281 		BRCM_encode_baud_rate(baudrate, &hci_update_baud_rate[6]);
282 	}
283 
284 	return(0);
285 }
286 
287 int
parse_bdaddr(char * optarg)288 parse_bdaddr(char *optarg)
289 {
290 	int bd_addr[6];
291 	int i;
292 
293 	sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X",
294 		&bd_addr[5], &bd_addr[4], &bd_addr[3],
295 		&bd_addr[2], &bd_addr[1], &bd_addr[0]);
296 
297 	for (i = 0; i < 6; i++) {
298 		hci_write_bd_addr[4 + i] = bd_addr[i];
299 	}
300 
301 	bdaddr_flag = 1;
302 
303 	return(0);
304 }
305 
306 int
readApName(char * name,int len)307 readApName(char *name, int len)
308 {
309 	FILE* devInfo = NULL;
310 
311     if(len < AP_NAME_SUFFIX_LEN) {
312         return -1;
313     }
314 
315     devInfo = fopen("/data/cfg/device_info.txt","rb+");
316     if(devInfo) {
317         fseek(devInfo, 36, SEEK_SET);
318         fread(name, 1, AP_NAME_SUFFIX_LEN, devInfo);
319         fclose(devInfo);
320         // is default value or not
321         if(0 == strncmp(name, "11:22:33:44:55:66", 17)) {
322             return -1;
323         }
324     } else {
325         return -1;
326     }
327 
328     return 0;
329 }
330 
331 int
writeApName(const char * name,int len)332 writeApName(const char* name, int len)
333 {
334 	FILE* devInfo = NULL;
335     char nameBuf[AP_NAME_SUFFIX_LEN] = {0};
336 
337     if(len < 17) {
338         return;
339     }
340 
341     if(0 != strncmp(name, "11:22:33:44:55", 17)) {
342         devInfo = fopen("/data/cfg/device_info.txt","rb+");
343         if(devInfo) {
344             fseek(devInfo, 36, SEEK_SET);
345             snprintf(nameBuf, AP_NAME_SUFFIX_LEN, "%s", name);
346             fwrite(nameBuf, 1, AP_NAME_SUFFIX_LEN, devInfo);
347             fflush(devInfo);
348             fsync(fileno(devInfo));
349             fclose(devInfo);
350         }
351         system("cp /data/cfg/device_info.txt /data/cfg/device_info");
352     }
353 }
354 
355 int
parse_bdaddr_rand(char * optarg)356 parse_bdaddr_rand(char *optarg)
357 {
358 	int bd_addr[6];
359 	int i,j;
360 	char optargtest[18];
361 
362 	char mh[]=":";
363 	char metachar[]="ABCDEF0123456789";
364 	if(0 != readApName(optargtest,AP_NAME_SUFFIX_LEN)){
365 		srand(time(NULL));
366 		for(j=0;j<17;j++){
367 			if(j%3 == 2){
368 			optargtest[j]= mh[0];
369 			}else{
370 				optargtest[j] = metachar[rand()%16];
371 			}
372 		}
373 		optargtest[17]="\0";
374 
375 		writeApName(optargtest,AP_NAME_SUFFIX_LEN);
376 	}
377 
378 	sscanf(optargtest, "%02X:%02X:%02X:%02X:%02X:%02X",
379 		&bd_addr[5], &bd_addr[4], &bd_addr[3],
380 		&bd_addr[2], &bd_addr[1], &bd_addr[0]);
381 
382 	for (i = 0; i < 6; i++) {
383 		hci_write_bd_addr[4 + i] = bd_addr[i];
384 	}
385 
386 	bdaddr_flag = 1;
387 
388 	return(0);
389 }
390 
391 int
parse_enable_lpm(char * optarg)392 parse_enable_lpm(char *optarg)
393 {
394 	enable_lpm = 1;
395 	return(0);
396 }
397 
398 int
parse_use_baudrate_for_download(char * optarg)399 parse_use_baudrate_for_download(char *optarg)
400 {
401 	use_baudrate_for_download = 1;
402 	return(0);
403 }
404 
405 int
parse_enable_hci(char * optarg)406 parse_enable_hci(char *optarg)
407 {
408 	enable_hci = 1;
409 	return(0);
410 }
411 
412 int
parse_scopcm(char * optarg)413 parse_scopcm(char *optarg)
414 {
415 	int param[10];
416 	int ret;
417 	int i;
418 
419 	ret = sscanf(optarg, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
420 		&param[0], &param[1], &param[2], &param[3], &param[4],
421 		&param[5], &param[6], &param[7], &param[8], &param[9]);
422 
423 	if (ret != 10) {
424 		return(1);
425 	}
426 
427 	scopcm = 1;
428 
429 	for (i = 0; i < 5; i++) {
430 		hci_write_sco_pcm_int[4 + i] = param[i];
431 	}
432 
433 	for (i = 0; i < 5; i++) {
434 		hci_write_pcm_data_format[4 + i] = param[5 + i];
435 	}
436 
437 	return(0);
438 }
439 
440 int
parse_i2s(char * optarg)441 parse_i2s(char *optarg)
442 {
443 	int param[4];
444 	int ret;
445 	int i;
446 
447 	ret = sscanf(optarg, "%d,%d,%d,%d", &param[0], &param[1], &param[2],
448 		&param[3]);
449 
450 	if (ret != 4) {
451 		return(1);
452 	}
453 
454 	i2s = 1;
455 
456 	for (i = 0; i < 4; i++) {
457 		hci_write_i2spcm_interface_param[4 + i] = param[i];
458 	}
459 
460 	return(0);
461 }
462 
463 int
parse_no2bytes(char * optarg)464 parse_no2bytes(char *optarg)
465 {
466 	no2bytes = 1;
467 	return(0);
468 }
469 
470 int
parse_tosleep(char * optarg)471 parse_tosleep(char *optarg)
472 {
473 	tosleep = atoi(optarg);
474 
475 	if (tosleep <= 0) {
476 		return(1);
477 	}
478 
479 	return(0);
480 }
481 
482 void
usage(char * argv0)483 usage(char *argv0)
484 {
485 	printf("Usage %s:\n", argv0);
486 	printf("\t<-d> to print a debug log\n");
487 	printf("\t<--patchram patchram_file>\n");
488 	printf("\t<--baudrate baud_rate>\n");
489 	printf("\t<--bd_addr bd_address>\n");
490 	printf("\t<--enable_lpm>\n");
491 	printf("\t<--enable_hci>\n");
492 	printf("\t<--use_baudrate_for_download> - Uses the\n");
493 	printf("\t\tbaudrate for downloading the firmware\n");
494 	printf("\t<--scopcm=sco_routing,pcm_interface_rate,frame_type,\n");
495 	printf("\t\tsync_mode,clock_mode,lsb_first,fill_bits,\n");
496 	printf("\t\tfill_method,fill_num,right_justify>\n");
497 	printf("\n\t\tWhere\n");
498 	printf("\n\t\tsco_routing is 0 for PCM, 1 for Transport,\n");
499 	printf("\t\t2 for Codec and 3 for I2S,\n");
500 	printf("\n\t\tpcm_interface_rate is 0 for 128KBps, 1 for\n");
501 	printf("\t\t256 KBps, 2 for 512KBps, 3 for 1024KBps,\n");
502 	printf("\t\tand 4 for 2048Kbps,\n");
503 	printf("\n\t\tframe_type is 0 for short and 1 for long,\n");
504 	printf("\t\tsync_mode is 0 for slave and 1 for master,\n");
505 	printf("\n\t\tclock_mode is 0 for slabe and 1 for master,\n");
506 	printf("\n\t\tlsb_first is 0 for false aand 1 for true,\n");
507 	printf("\n\t\tfill_bits is the value in decimal for unused bits,\n");
508 	printf("\n\t\tfill_method is 0 for 0's and 1 for 1's, 2 for\n");
509 	printf("\t\tsigned and 3 for programmable,\n");
510 	printf("\n\t\tfill_num is the number or bits to fill,\n");
511 	printf("\n\t\tright_justify is 0 for false and 1 for true\n");
512 	printf("\n\t<--i2s=i2s_enable,is_master,sample_rate,clock_rate>\n");
513 	printf("\n\t\tWhere\n");
514 	printf("\n\t\ti2s_enable is 0 for disable and 1 for enable,\n");
515 	printf("\n\t\tis_master is 0 for slave and 1 for master,\n");
516 	printf("\n\t\tsample_rate is 0 for 8KHz, 1 for 16Khz and\n");
517 	printf("\t\t2 for 4 KHz,\n");
518 	printf("\n\t\tclock_rate is 0 for 128KHz, 1 for 256KHz, 3 for\n");
519 	printf("\t\t1024 KHz and 4 for 2048 KHz.\n\n");
520 	printf("\t<--no2bytes skips waiting for two byte confirmation\n");
521 	printf("\t\tbefore starting patchram download. Newer chips\n");
522 	printf("\t\tdo not generate these two bytes.>\n");
523 	printf("\t<--tosleep=microseconds>\n");
524 	printf("\tuart_device_name\n");
525 }
526 
527 int
parse_cmd_line(int argc,char ** argv)528 parse_cmd_line(int argc, char **argv)
529 {
530 	int c;
531 	int ret = 0;
532 
533 	typedef int (*PFI)();
534 
535 	PFI parse[] = { parse_patchram, parse_baudrate,
536 		parse_bdaddr,parse_bdaddr_rand, parse_enable_lpm, parse_enable_hci,
537 		parse_use_baudrate_for_download,
538 		parse_scopcm, parse_i2s, parse_no2bytes, parse_tosleep};
539 
540 	while (1) {
541 		int this_option_optind = optind ? optind : 1;
542 		int option_index = 0;
543 
544 		static struct option long_options[] = {
545 			{"patchram", 1, 0, 0},
546 			{"baudrate", 1, 0, 0},
547 			{"bd_addr", 1, 0, 0},
548 			{"bd_addr_rand", 0, 0, 0},
549 			{"enable_lpm", 0, 0, 0},
550 			{"enable_hci", 0, 0, 0},
551 			{"use_baudrate_for_download", 0, 0, 0},
552 			{"scopcm", 1, 0, 0},
553 			{"i2s", 1, 0, 0},
554 			{"no2bytes", 0, 0, 0},
555 			{"tosleep", 1, 0, 0},
556 			{0, 0, 0, 0}
557 		};
558 
559 		c = getopt_long_only (argc, argv, "d", long_options,
560 				&option_index);
561 
562 		if (c == -1) {
563 			break;
564 		}
565 
566 		switch (c) {
567 			case 0:
568 				if (debug) {
569 					printf ("option %s",
570 						long_options[option_index].name);
571 					if (optarg)
572 						printf (" with arg %s", optarg);
573 					printf ("\n");
574 				}
575 
576 				ret = (*parse[option_index])(optarg);
577 
578 				break;
579 			case 'd':
580 				debug = 1;
581 				break;
582 
583 			case '?':
584 				//nobreak
585 			default:
586 				usage(argv[0]);
587 				break;
588 		}
589 
590 		if (ret) {
591 			usage(argv[0]);
592 			break;
593 		}
594 	}
595 
596 	if (ret) {
597 		return(1);
598 	}
599 
600 	if (optind < argc) {
601 		if (debug)
602 			printf ("%s \n", argv[optind]);
603 		if ((uart_fd = open(argv[optind], O_RDWR | O_NOCTTY)) == -1) {
604 			fprintf(stderr, "port %s could not be opened, error %d\n",
605 					argv[2], errno);
606 		}
607 	}
608 
609 	return(0);
610 }
611 
612 void
init_uart()613 init_uart()
614 {
615 	tcflush(uart_fd, TCIOFLUSH);
616 	tcgetattr(uart_fd, &termios);
617 
618 #ifndef __CYGWIN__
619 	cfmakeraw(&termios);
620 #else
621 	termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
622                 | INLCR | IGNCR | ICRNL | IXON);
623 	termios.c_oflag &= ~OPOST;
624 	termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
625 	termios.c_cflag &= ~(CSIZE | PARENB);
626 	termios.c_cflag |= CS8;
627 #endif
628 
629 	termios.c_cflag |= CRTSCTS;
630 	tcsetattr(uart_fd, TCSANOW, &termios);
631 	tcflush(uart_fd, TCIOFLUSH);
632 	tcsetattr(uart_fd, TCSANOW, &termios);
633 	tcflush(uart_fd, TCIOFLUSH);
634 	tcflush(uart_fd, TCIOFLUSH);
635 	cfsetospeed(&termios, B115200);
636 	cfsetispeed(&termios, B115200);
637 	tcsetattr(uart_fd, TCSANOW, &termios);
638 }
639 
640 void
dump(uchar * out,int len)641 dump(uchar *out, int len)
642 {
643 	int i;
644 
645 	for (i = 0; i < len; i++) {
646 		if (i && !(i % 16)) {
647 			fprintf(stderr, "\n");
648 		}
649 
650 		fprintf(stderr, "%02x ", out[i]);
651 	}
652 
653 	fprintf(stderr, "\n");
654 }
655 
656 void
read_event(int fd,uchar * buffer)657 read_event(int fd, uchar *buffer)
658 {
659 	int i = 0;
660 	int len = 3;
661 	int count;
662 
663 	while ((count = read(fd, &buffer[i], len)) < len) {
664 		i += count;
665 		len -= count;
666 		//fprintf(stderr, "received11 %d\n", count);
667 	}
668 
669 	i += count;
670 	len = buffer[2];
671 	//fprintf(stderr, "received22 %d\n", count);
672 
673 	while ((count = read(fd, &buffer[i], len)) < len) {
674 		i += count;
675 		len -= count;
676 	}
677 	//fprintf(stderr, "received33 %d\n", count);
678 
679 	if (debug) {
680 		count += i;
681 
682 		fprintf(stderr, "received %d\n", count);
683 		dump(buffer, count);
684 	}
685 }
686 
687 void
hci_send_cmd(uchar * buf,int len)688 hci_send_cmd(uchar *buf, int len)
689 {
690 	if (debug) {
691 		fprintf(stderr, "writing\n");
692 		dump(buf, len);
693 	}
694 
695 	write(uart_fd, buf, len);
696 }
697 
698 void
expired(int sig)699 expired(int sig)
700 {
701 	hci_send_cmd(hci_reset, sizeof(hci_reset));
702 	alarm(4);
703 }
704 
705 void
proc_reset()706 proc_reset()
707 {
708 	signal(SIGALRM, expired);
709 
710 	fprintf(stderr, "proc_reset");
711 
712 	hci_send_cmd(hci_reset, sizeof(hci_reset));
713 
714 	alarm(4);
715 
716 	read_event(uart_fd, buffer);
717 
718 	alarm(0);
719 }
720 
721 void
proc_patchram()722 proc_patchram()
723 {
724 	int len;
725 
726 	hci_send_cmd(hci_download_minidriver, sizeof(hci_download_minidriver));
727 
728 	fprintf(stderr, "send hci_download_minidriver");
729 
730 	read_event(uart_fd, buffer);
731 
732 	if (!no2bytes) {
733 		read(uart_fd, &buffer[0], 2);
734 	}
735 
736 	if (tosleep) {
737 		usleep(tosleep);
738 	}
739 
740 	while (read(hcdfile_fd, &buffer[1], 3)) {
741 		buffer[0] = 0x01;
742 
743 		len = buffer[3];
744 
745 		read(hcdfile_fd, &buffer[4], len);
746 
747 		hci_send_cmd(buffer, len + 4);
748 
749 		read_event(uart_fd, buffer);
750 	}
751 	usleep(200000);
752 
753 	if (use_baudrate_for_download) {
754 		cfsetospeed(&termios, B115200);
755 		cfsetispeed(&termios, B115200);
756 		tcsetattr(uart_fd, TCSANOW, &termios);
757 	}
758 	proc_reset();
759 }
760 
761 void
proc_baudrate()762 proc_baudrate()
763 {
764 	hci_send_cmd(hci_update_baud_rate, sizeof(hci_update_baud_rate));
765 
766 	read_event(uart_fd, buffer);
767 
768 	usleep(200000);
769 
770 	cfsetospeed(&termios, termios_baudrate);
771 	cfsetispeed(&termios, termios_baudrate);
772 	tcsetattr(uart_fd, TCSANOW, &termios);
773 
774 	if (debug) {
775 		fprintf(stderr, "Done setting baudrate\n");
776 	}
777 }
778 
779 void
proc_bdaddr()780 proc_bdaddr()
781 {
782 	hci_send_cmd(hci_write_bd_addr, sizeof(hci_write_bd_addr));
783 
784 	read_event(uart_fd, buffer);
785 }
786 
787 void
proc_enable_lpm()788 proc_enable_lpm()
789 {
790 	hci_send_cmd(hci_write_sleep_mode, sizeof(hci_write_sleep_mode));
791 
792 	read_event(uart_fd, buffer);
793 }
794 
795 void
proc_scopcm()796 proc_scopcm()
797 {
798 	hci_send_cmd(hci_write_sco_pcm_int,
799 		sizeof(hci_write_sco_pcm_int));
800 
801 	read_event(uart_fd, buffer);
802 
803 	hci_send_cmd(hci_write_pcm_data_format,
804 		sizeof(hci_write_pcm_data_format));
805 
806 	read_event(uart_fd, buffer);
807 }
808 
809 void
proc_i2s()810 proc_i2s()
811 {
812 	hci_send_cmd(hci_write_i2spcm_interface_param,
813 		sizeof(hci_write_i2spcm_interface_param));
814 
815 	read_event(uart_fd, buffer);
816 }
817 
818 void
proc_enable_hci()819 proc_enable_hci()
820 {
821 	int i = N_HCI;
822 	int proto = HCI_UART_H4;
823 	if (ioctl(uart_fd, TIOCSETD, &i) < 0) {
824 		fprintf(stderr, "Can't set line discipline\n");
825 		return;
826 	}
827 
828 	if (ioctl(uart_fd, HCIUARTSETPROTO, proto) < 0) {
829 		fprintf(stderr, "Can't set hci protocol\n");
830 		return;
831 	}
832 	fprintf(stderr, "Done setting line discpline\n");
833 	return;
834 }
835 
836 #ifdef ANDROID
837 void
read_default_bdaddr()838 read_default_bdaddr()
839 {
840 	int sz;
841 	int fd;
842 
843 	char path[PROPERTY_VALUE_MAX];
844 
845 	char bdaddr[18];
846 	int len = 17;
847 	memset(bdaddr, 0, (len + 1) * sizeof(char));
848 
849 	property_get("ro.bt.bdaddr_path", path, "");
850 	if (path[0] == 0)
851 		return;
852 
853 	fd = open(path, O_RDONLY);
854 	if (fd < 0) {
855 		fprintf(stderr, "open(%s) failed: %s (%d)", path, strerror(errno),
856 				errno);
857 		return;
858 	}
859 
860 	sz = read(fd, bdaddr, len);
861 	if (sz < 0) {
862 		fprintf(stderr, "read(%s) failed: %s (%d)", path, strerror(errno),
863 				errno);
864 		close(fd);
865 		return;
866 	} else if (sz != len) {
867 		fprintf(stderr, "read(%s) unexpected size %d", path, sz);
868 		close(fd);
869 		return;
870 	}
871 
872 	if (debug) {
873 		printf("Read default bdaddr of %s\n", bdaddr);
874 	}
875 
876 	parse_bdaddr(bdaddr);
877 }
878 #endif
879 
880 
881 int
main(int argc,char ** argv)882 main (int argc, char **argv)
883 {
884 #ifdef ANDROID
885 	read_default_bdaddr();
886 #endif
887 
888 	if (parse_cmd_line(argc, argv)) {
889 		exit(1);
890 	}
891 
892 	if (uart_fd < 0) {
893 		exit(2);
894 	}
895 
896 	init_uart();
897 
898 	proc_reset();
899 
900 	if (use_baudrate_for_download) {
901 		if (termios_baudrate) {
902 			proc_baudrate();
903 		}
904 	}
905 
906 	if (hcdfile_fd > 0) {
907 		proc_patchram();
908 	}
909 
910 	if (termios_baudrate) {
911 		proc_baudrate();
912 	}
913 
914 	if (bdaddr_flag) {
915 		proc_bdaddr();
916 	}
917 
918 	if (enable_lpm) {
919 		proc_enable_lpm();
920 	}
921 
922 	if (scopcm) {
923 		proc_scopcm();
924 	}
925 
926 	if (i2s) {
927 		proc_i2s();
928 	}
929 
930 	if (enable_hci) {
931 		proc_enable_hci();
932 
933 		while (1) {
934 			sleep(UINT_MAX);
935 		}
936 	}
937 
938 	exit(0);
939 }
940