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