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 ¶m[0], ¶m[1], ¶m[2], ¶m[3], ¶m[4],
471 ¶m[5], ¶m[6], ¶m[7], ¶m[8], ¶m[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", ¶m[0], ¶m[1], ¶m[2],
498 ¶m[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